<div class="tutorial-bundle" data-metadata-json='{"difficulty": "advanced", "groupedProjectAssets": [{"name": "Boing bats", "assets": ["images/player-normal.png", "images/player-flash.png", "images/robot-normal.png", "images/robot-flash.png"]}]}' data-tip-sha1="6290e7b396a295c1ec55fd7852f9afb43bcdcd2b"><div class="front-matter" data-complete-code-text="# You're the player on the left --- use the W/S keys to move your bat!

import pytch
import random


class BoingBackground(pytch.Stage):
    Backdrops = [&quot;table.png&quot;]


class PlayerBat(pytch.Sprite):
    Costumes = [&quot;player-normal.png&quot;, &quot;player-flash.png&quot;]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(-215, 0)

        while True:
            if pytch.key_pressed(&quot;w&quot;) and self.y_position &lt; 117:
                self.change_y(3)
            if pytch.key_pressed(&quot;s&quot;) and self.y_position &gt; -117:
                self.change_y(-3)

    @pytch.when_I_receive(&quot;player-hit&quot;)
    def flash_briefly(self):
        self.switch_costume(&quot;player-flash&quot;)
        pytch.wait_seconds(0.1)
        self.switch_costume(&quot;player-normal&quot;)


class RobotBat(pytch.Sprite):
    Costumes = [&quot;robot-normal.png&quot;, &quot;robot-flash.png&quot;]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(215, 0)

        while True:
            target_y = Ball.the_original().y_position
            if target_y &lt; -117:
                target_y = -117
            if target_y &gt; 117:
                target_y = 117
            self.set_y(target_y)

    @pytch.when_I_receive(&quot;robot-hit&quot;)
    def flash_briefly(self):
        self.switch_costume(&quot;robot-flash&quot;)
        pytch.wait_seconds(0.1)
        self.switch_costume(&quot;robot-normal&quot;)


class Ball(pytch.Sprite):
    Costumes = [&quot;ball.png&quot;]
    Sounds = [&quot;hit.mp3&quot;, &quot;bounce.mp3&quot;, &quot;lost.mp3&quot;]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(0, 0)

        x_speed = 3
        y_speed = 0
        while True:
            self.change_x(x_speed)

            if self.x_position &gt; 203:
                self.change_x(-x_speed)
                x_speed = -x_speed

                if y_speed == 0:
                    y_speed = random.choice([-1, 1])

                pytch.broadcast(&quot;robot-hit&quot;)
                self.start_sound(&quot;hit&quot;)

            if self.x_position &lt; -203:
                player_y = PlayerBat.the_original().y_position
                position_on_bat = self.y_position - player_y
                if (position_on_bat &gt;= -45) and (position_on_bat &lt;= 45):
                    y_speed = int(position_on_bat / 10)
                    self.change_x(-x_speed)
                    x_speed = -x_speed
                    pytch.broadcast(&quot;player-hit&quot;)
                    self.start_sound(&quot;hit&quot;)
                else:
                    for i in range(10):
                        self.change_x(x_speed)
                        self.change_y(y_speed)
                    self.hide()
                    self.start_sound(&quot;lost&quot;)
                    break

            self.change_y(y_speed)

            if self.y_position &gt; 158 or self.y_position &lt; -158:
                self.change_y(-y_speed)
                y_speed = -y_speed
                self.start_sound(&quot;bounce&quot;)
" data-initial-code-text="import pytch
"><h1>Boing: Make a Pong-like game</h1><p>In this tutorial we will make a version of the classic game
<a href="https://en.wikipedia.org/wiki/Pong">Pong</a>.  We are going to use the graphics,
and some of the ideas, kindly made available by the <a href="https://wireframe.raspberrypi.org/books/code-the-classics1">Code the
Classics</a> book
published by the Raspberry Pi organisation.</p></div><div class="chapter-content"><h2>Make the playing area</h2><p>We first set up the <em>Stage</em>, which, like Scratch, is where the action takes
place.  We're going to use the same image as the version in <em>Code the Classics</em>.
We define a <code>class</code> which is based on the built-in <code>pytch.Stage</code>, and say what
<em>Backdrops</em> we want it to have.  In Pytch we can do this by giving a <em>list</em> of
backdrop filenames.  Here we only have one backdrop, so our list just has one
entry.</p><div class="patch-container" data-code-as-of-commit='import pytch


class BoingBackground(pytch.Stage):
    Backdrops = ["table.png"]
' data-slug="add-stage-with-background"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>1</pre></td><td class="linenum"><pre>1</pre></td><td><pre>import pytch</pre></td></tr></tbody><tbody class="diff-add" data-added-text='

class BoingBackground(pytch.Stage):
    Backdrops = ["table.png"]
'><tr><td class="linenum"></td><td class="linenum"><pre>2</pre></td><td><pre></pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>3</pre></td><td><pre></pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>4</pre></td><td><pre>class BoingBackground(pytch.Stage):</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>5</pre></td><td><pre>    Backdrops = ["table.png"]</pre></td></tr></tbody></table></div></div></div><div class="chapter-content"><h2>Add the player's bat</h2><p>Now we have the background, we want to put the player's bat into the
game.  The first part of this is similar to how we introduced the
<em>BoingBackground</em>.  We define <em>PlayerBat</em>, which we say is a kind of
<em>Sprite</em>.  Again, its <em>Costumes</em> list only has one entry.</p><div class="patch-container" data-code-as-of-commit='import pytch


class BoingBackground(pytch.Stage):
    Backdrops = ["table.png"]


class PlayerBat(pytch.Sprite):
    Costumes = ["player-normal.png"]
' data-slug="add-Player-with-costume"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>3</pre></td><td class="linenum"><pre>3</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>4</pre></td><td class="linenum"><pre>4</pre></td><td><pre>class BoingBackground(pytch.Stage):</pre></td></tr><tr><td class="linenum"><pre>5</pre></td><td class="linenum"><pre>5</pre></td><td><pre>    Backdrops = ["table.png"]</pre></td></tr></tbody><tbody class="diff-add" data-added-text='

class PlayerBat(pytch.Sprite):
    Costumes = ["player-normal.png"]
'><tr><td class="linenum"></td><td class="linenum"><pre>6</pre></td><td><pre></pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>7</pre></td><td><pre></pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>8</pre></td><td><pre>class PlayerBat(pytch.Sprite):</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>9</pre></td><td><pre>    Costumes = ["player-normal.png"]</pre></td></tr></tbody></table></div></div><p>When the green flag is clicked, we want the player's bat to go to its
starting position:</p><div class="patch-container" data-code-as-of-commit='import pytch


class BoingBackground(pytch.Stage):
    Backdrops = ["table.png"]


class PlayerBat(pytch.Sprite):
    Costumes = ["player-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(-215, 0)
' data-slug="init-Player-on-green-flag"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>7</pre></td><td class="linenum"><pre>7</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>8</pre></td><td class="linenum"><pre>8</pre></td><td><pre>class PlayerBat(pytch.Sprite):</pre></td></tr><tr><td class="linenum"><pre>9</pre></td><td class="linenum"><pre>9</pre></td><td><pre>    Costumes = ["player-normal.png"]</pre></td></tr></tbody><tbody class="diff-add" data-added-text="
    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(-215, 0)
"><tr><td class="linenum"></td><td class="linenum"><pre>10</pre></td><td><pre></pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>11</pre></td><td><pre>    @pytch.when_green_flag_clicked</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>12</pre></td><td><pre>    def play(self):</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>13</pre></td><td><pre>        self.go_to_xy(-215, 0)</pre></td></tr></tbody></table></div></div><p>Once the game has started, the person playing the game needs to be
able to move the bat.  We do this by continually checking whether the
person is pressing the <code>W</code> key to move up, or the <code>S</code> key to move
down.  If they are, we change the bat's <em>y</em> coordinate:</p><div class="patch-container" data-code-as-of-commit='import pytch


class BoingBackground(pytch.Stage):
    Backdrops = ["table.png"]


class PlayerBat(pytch.Sprite):
    Costumes = ["player-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(-215, 0)

        while True:
            if pytch.key_pressed("w"):
                self.change_y(3)
            if pytch.key_pressed("s"):
                self.change_y(-3)
' data-slug="move-Player-with-W-and-S"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>11</pre></td><td class="linenum"><pre>11</pre></td><td><pre>    @pytch.when_green_flag_clicked</pre></td></tr><tr><td class="linenum"><pre>12</pre></td><td class="linenum"><pre>12</pre></td><td><pre>    def play(self):</pre></td></tr><tr><td class="linenum"><pre>13</pre></td><td class="linenum"><pre>13</pre></td><td><pre>        self.go_to_xy(-215, 0)</pre></td></tr></tbody><tbody class="diff-add" data-added-text='
        while True:
            if pytch.key_pressed("w"):
                self.change_y(3)
            if pytch.key_pressed("s"):
                self.change_y(-3)
'><tr><td class="linenum"></td><td class="linenum"><pre>14</pre></td><td><pre></pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>15</pre></td><td><pre>        while True:</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>16</pre></td><td><pre>            if pytch.key_pressed("w"):</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>17</pre></td><td><pre>                self.change_y(3)</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>18</pre></td><td><pre>            if pytch.key_pressed("s"):</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>19</pre></td><td><pre>                self.change_y(-3)</pre></td></tr></tbody></table></div></div><p>If you play the game now, you'll see a problem.  You can move the bat
right off the top of the stage.  To stop this, we'll only move if
you're pressing <code>W</code> and you're low enough that moving up is allowed.
We'll make the same change to the 'move down' part of the code:</p><div class="patch-container" data-code-as-of-commit='import pytch


class BoingBackground(pytch.Stage):
    Backdrops = ["table.png"]


class PlayerBat(pytch.Sprite):
    Costumes = ["player-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(-215, 0)

        while True:
            if pytch.key_pressed("w") and self.y_position &lt; 117:
                self.change_y(3)
            if pytch.key_pressed("s") and self.y_position &gt; -117:
                self.change_y(-3)
' data-slug="limit-Player-y-coord"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>13</pre></td><td class="linenum"><pre>13</pre></td><td><pre>        self.go_to_xy(-215, 0)</pre></td></tr><tr><td class="linenum"><pre>14</pre></td><td class="linenum"><pre>14</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>15</pre></td><td class="linenum"><pre>15</pre></td><td><pre>        while True:</pre></td></tr></tbody><tbody class="diff-del"><tr><td class="linenum"><pre>16</pre></td><td class="linenum"></td><td><pre>            if pytch.key_pressed("w"):</pre></td></tr></tbody><tbody class="diff-add" data-added-text='            if pytch.key_pressed("w") and self.y_position &lt; 117:
'><tr><td class="linenum"></td><td class="linenum"><pre>16</pre></td><td><pre>            if pytch.key_pressed("w") and self.y_position &lt; 117:</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>17</pre></td><td class="linenum"><pre>17</pre></td><td><pre>                self.change_y(3)</pre></td></tr></tbody><tbody class="diff-del"><tr><td class="linenum"><pre>18</pre></td><td class="linenum"></td><td><pre>            if pytch.key_pressed("s"):</pre></td></tr></tbody><tbody class="diff-add" data-added-text='            if pytch.key_pressed("s") and self.y_position &gt; -117:
'><tr><td class="linenum"></td><td class="linenum"><pre>18</pre></td><td><pre>            if pytch.key_pressed("s") and self.y_position &gt; -117:</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>19</pre></td><td class="linenum"><pre>19</pre></td><td><pre>                self.change_y(-3)</pre></td></tr></tbody></table></div></div></div><div class="chapter-content"><h2>Add the ball</h2><p>The next thing to add is the ball.  We do this in a very similar way
to how we added the player's bat.  The ball only has one costume, and
we tell Pytch which file to use:</p><div class="patch-container" data-code-as-of-commit='import pytch


class BoingBackground(pytch.Stage):
    Backdrops = ["table.png"]


class PlayerBat(pytch.Sprite):
    Costumes = ["player-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(-215, 0)

        while True:
            if pytch.key_pressed("w") and self.y_position &lt; 117:
                self.change_y(3)
            if pytch.key_pressed("s") and self.y_position &gt; -117:
                self.change_y(-3)


class Ball(pytch.Sprite):
    Costumes = ["ball.png"]
' data-slug="add-Ball-with-costume"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>17</pre></td><td class="linenum"><pre>17</pre></td><td><pre>                self.change_y(3)</pre></td></tr><tr><td class="linenum"><pre>18</pre></td><td class="linenum"><pre>18</pre></td><td><pre>            if pytch.key_pressed("s") and self.y_position &gt; -117:</pre></td></tr><tr><td class="linenum"><pre>19</pre></td><td class="linenum"><pre>19</pre></td><td><pre>                self.change_y(-3)</pre></td></tr></tbody><tbody class="diff-add" data-added-text='

class Ball(pytch.Sprite):
    Costumes = ["ball.png"]
'><tr><td class="linenum"></td><td class="linenum"><pre>20</pre></td><td><pre></pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>21</pre></td><td><pre></pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>22</pre></td><td><pre>class Ball(pytch.Sprite):</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>23</pre></td><td><pre>    Costumes = ["ball.png"]</pre></td></tr></tbody></table></div></div><p>When the green flag is clicked, the ball should go to the very centre
of the screen:</p><div class="patch-container" data-code-as-of-commit='import pytch


class BoingBackground(pytch.Stage):
    Backdrops = ["table.png"]


class PlayerBat(pytch.Sprite):
    Costumes = ["player-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(-215, 0)

        while True:
            if pytch.key_pressed("w") and self.y_position &lt; 117:
                self.change_y(3)
            if pytch.key_pressed("s") and self.y_position &gt; -117:
                self.change_y(-3)


class Ball(pytch.Sprite):
    Costumes = ["ball.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(0, 0)
' data-slug="centre-Ball-on-green-flag"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>21</pre></td><td class="linenum"><pre>21</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>22</pre></td><td class="linenum"><pre>22</pre></td><td><pre>class Ball(pytch.Sprite):</pre></td></tr><tr><td class="linenum"><pre>23</pre></td><td class="linenum"><pre>23</pre></td><td><pre>    Costumes = ["ball.png"]</pre></td></tr></tbody><tbody class="diff-add" data-added-text="
    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(0, 0)
"><tr><td class="linenum"></td><td class="linenum"><pre>24</pre></td><td><pre></pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>25</pre></td><td><pre>    @pytch.when_green_flag_clicked</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>26</pre></td><td><pre>    def play(self):</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>27</pre></td><td><pre>        self.go_to_xy(0, 0)</pre></td></tr></tbody></table></div></div><p>Then it should straight away start moving away from the player, to
give them time to get ready.  We do this by continually changing the
ball's <em>x</em> coordinate:</p><div class="patch-container" data-code-as-of-commit='import pytch


class BoingBackground(pytch.Stage):
    Backdrops = ["table.png"]


class PlayerBat(pytch.Sprite):
    Costumes = ["player-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(-215, 0)

        while True:
            if pytch.key_pressed("w") and self.y_position &lt; 117:
                self.change_y(3)
            if pytch.key_pressed("s") and self.y_position &gt; -117:
                self.change_y(-3)


class Ball(pytch.Sprite):
    Costumes = ["ball.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(0, 0)

        while True:
            self.change_x(3)
' data-slug="move-Ball-across-screen"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>25</pre></td><td class="linenum"><pre>25</pre></td><td><pre>    @pytch.when_green_flag_clicked</pre></td></tr><tr><td class="linenum"><pre>26</pre></td><td class="linenum"><pre>26</pre></td><td><pre>    def play(self):</pre></td></tr><tr><td class="linenum"><pre>27</pre></td><td class="linenum"><pre>27</pre></td><td><pre>        self.go_to_xy(0, 0)</pre></td></tr></tbody><tbody class="diff-add" data-added-text="
        while True:
            self.change_x(3)
"><tr><td class="linenum"></td><td class="linenum"><pre>28</pre></td><td><pre></pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>29</pre></td><td><pre>        while True:</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>30</pre></td><td><pre>            self.change_x(3)</pre></td></tr></tbody></table></div></div><p>The problem here is that the ball of course just keeps going right
off the edge of the screen.  We know we're going to need to keep track
of which direction the ball is going, so we bring in a <em>local variable</em>
<code>x_speed</code>.  This variable only exists inside the <code>play()</code> method.</p><div class="patch-container" data-code-as-of-commit='import pytch


class BoingBackground(pytch.Stage):
    Backdrops = ["table.png"]


class PlayerBat(pytch.Sprite):
    Costumes = ["player-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(-215, 0)

        while True:
            if pytch.key_pressed("w") and self.y_position &lt; 117:
                self.change_y(3)
            if pytch.key_pressed("s") and self.y_position &gt; -117:
                self.change_y(-3)


class Ball(pytch.Sprite):
    Costumes = ["ball.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(0, 0)

        x_speed = 3
        while True:
            self.change_x(x_speed)
' data-slug="add-Ball-state-x-speed"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>26</pre></td><td class="linenum"><pre>26</pre></td><td><pre>    def play(self):</pre></td></tr><tr><td class="linenum"><pre>27</pre></td><td class="linenum"><pre>27</pre></td><td><pre>        self.go_to_xy(0, 0)</pre></td></tr><tr><td class="linenum"><pre>28</pre></td><td class="linenum"><pre>28</pre></td><td><pre></pre></td></tr></tbody><tbody class="diff-add" data-added-text="        x_speed = 3
"><tr><td class="linenum"></td><td class="linenum"><pre>29</pre></td><td><pre>        x_speed = 3</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>29</pre></td><td class="linenum"><pre>30</pre></td><td><pre>        while True:</pre></td></tr></tbody><tbody class="diff-del"><tr><td class="linenum"><pre>30</pre></td><td class="linenum"></td><td><pre>            self.change_x(3)</pre></td></tr></tbody><tbody class="diff-add" data-added-text="            self.change_x(x_speed)
"><tr><td class="linenum"></td><td class="linenum"><pre>31</pre></td><td><pre>            self.change_x(x_speed)</pre></td></tr></tbody></table></div></div><p>We'll leave the ball here until there is a robot bat for the player to
play against, which is what we'll do next.</p></div><div class="chapter-content"><h2>Add the robot opponent</h2><p>This is familiar by now.  We add <em>RobotBat</em>, which is a sort of
<em>Sprite</em>, with a costume:</p><div class="patch-container" data-code-as-of-commit='import pytch


class BoingBackground(pytch.Stage):
    Backdrops = ["table.png"]


class PlayerBat(pytch.Sprite):
    Costumes = ["player-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(-215, 0)

        while True:
            if pytch.key_pressed("w") and self.y_position &lt; 117:
                self.change_y(3)
            if pytch.key_pressed("s") and self.y_position &gt; -117:
                self.change_y(-3)


class RobotBat(pytch.Sprite):
    Costumes = ["robot-normal.png"]


class Ball(pytch.Sprite):
    Costumes = ["ball.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(0, 0)

        x_speed = 3
        while True:
            self.change_x(x_speed)
' data-slug="add-Robot-with-costume"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>19</pre></td><td class="linenum"><pre>19</pre></td><td><pre>                self.change_y(-3)</pre></td></tr><tr><td class="linenum"><pre>20</pre></td><td class="linenum"><pre>20</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>21</pre></td><td class="linenum"><pre>21</pre></td><td><pre></pre></td></tr></tbody><tbody class="diff-add" data-added-text='class RobotBat(pytch.Sprite):
    Costumes = ["robot-normal.png"]


'><tr><td class="linenum"></td><td class="linenum"><pre>22</pre></td><td><pre>class RobotBat(pytch.Sprite):</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>23</pre></td><td><pre>    Costumes = ["robot-normal.png"]</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>24</pre></td><td><pre></pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>25</pre></td><td><pre></pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>22</pre></td><td class="linenum"><pre>26</pre></td><td><pre>class Ball(pytch.Sprite):</pre></td></tr><tr><td class="linenum"><pre>23</pre></td><td class="linenum"><pre>27</pre></td><td><pre>    Costumes = ["ball.png"]</pre></td></tr><tr><td class="linenum"><pre>24</pre></td><td class="linenum"><pre>28</pre></td><td><pre></pre></td></tr></tbody></table></div></div><p>When the green flag is clicked, the robot bat will go to the right
place on the screen, which is at the right, vertically centred:</p><div class="patch-container" data-code-as-of-commit='import pytch


class BoingBackground(pytch.Stage):
    Backdrops = ["table.png"]


class PlayerBat(pytch.Sprite):
    Costumes = ["player-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(-215, 0)

        while True:
            if pytch.key_pressed("w") and self.y_position &lt; 117:
                self.change_y(3)
            if pytch.key_pressed("s") and self.y_position &gt; -117:
                self.change_y(-3)


class RobotBat(pytch.Sprite):
    Costumes = ["robot-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(215, 0)


class Ball(pytch.Sprite):
    Costumes = ["ball.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(0, 0)

        x_speed = 3
        while True:
            self.change_x(x_speed)
' data-slug="centre-Robot-on-green-flag"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>22</pre></td><td class="linenum"><pre>22</pre></td><td><pre>class RobotBat(pytch.Sprite):</pre></td></tr><tr><td class="linenum"><pre>23</pre></td><td class="linenum"><pre>23</pre></td><td><pre>    Costumes = ["robot-normal.png"]</pre></td></tr><tr><td class="linenum"><pre>24</pre></td><td class="linenum"><pre>24</pre></td><td><pre></pre></td></tr></tbody><tbody class="diff-add" data-added-text="    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(215, 0)

"><tr><td class="linenum"></td><td class="linenum"><pre>25</pre></td><td><pre>    @pytch.when_green_flag_clicked</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>26</pre></td><td><pre>    def play(self):</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>27</pre></td><td><pre>        self.go_to_xy(215, 0)</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>28</pre></td><td><pre></pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>25</pre></td><td class="linenum"><pre>29</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>26</pre></td><td class="linenum"><pre>30</pre></td><td><pre>class Ball(pytch.Sprite):</pre></td></tr><tr><td class="linenum"><pre>27</pre></td><td class="linenum"><pre>31</pre></td><td><pre>    Costumes = ["ball.png"]</pre></td></tr></tbody></table></div></div><p>Shortly we'll give the robot bat some intelligence, but next we'll
return to making the ball bounce.</p></div><div class="chapter-content"><h2>Bounce the ball off the bats: simple version</h2><p>The ball can tell if it's moved far enough to the right that it should
bounce off the robot.  Straight after the ball has moved, we want
check if it's moved too far.  If it has, we want to move <em>back</em> the
same amount we just moved, and then change our <code>x_speed</code> to be the
<em>opposite</em> of what it just was:</p><div class="patch-container" data-code-as-of-commit='import pytch


class BoingBackground(pytch.Stage):
    Backdrops = ["table.png"]


class PlayerBat(pytch.Sprite):
    Costumes = ["player-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(-215, 0)

        while True:
            if pytch.key_pressed("w") and self.y_position &lt; 117:
                self.change_y(3)
            if pytch.key_pressed("s") and self.y_position &gt; -117:
                self.change_y(-3)


class RobotBat(pytch.Sprite):
    Costumes = ["robot-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(215, 0)


class Ball(pytch.Sprite):
    Costumes = ["ball.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(0, 0)

        x_speed = 3
        while True:
            self.change_x(x_speed)

            if self.x_position &gt; 203:
                self.change_x(-x_speed)
                x_speed = -x_speed
' data-slug="bounce-Ball-off-Robot"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>37</pre></td><td class="linenum"><pre>37</pre></td><td><pre>        x_speed = 3</pre></td></tr><tr><td class="linenum"><pre>38</pre></td><td class="linenum"><pre>38</pre></td><td><pre>        while True:</pre></td></tr><tr><td class="linenum"><pre>39</pre></td><td class="linenum"><pre>39</pre></td><td><pre>            self.change_x(x_speed)</pre></td></tr></tbody><tbody class="diff-add" data-added-text="
            if self.x_position &gt; 203:
                self.change_x(-x_speed)
                x_speed = -x_speed
"><tr><td class="linenum"></td><td class="linenum"><pre>40</pre></td><td><pre></pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>41</pre></td><td><pre>            if self.x_position &gt; 203:</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>42</pre></td><td><pre>                self.change_x(-x_speed)</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>43</pre></td><td><pre>                x_speed = -x_speed</pre></td></tr></tbody></table></div></div><p>We can do the same to make the ball check if it's bounced off the
player's bat:</p><div class="patch-container" data-code-as-of-commit='import pytch


class BoingBackground(pytch.Stage):
    Backdrops = ["table.png"]


class PlayerBat(pytch.Sprite):
    Costumes = ["player-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(-215, 0)

        while True:
            if pytch.key_pressed("w") and self.y_position &lt; 117:
                self.change_y(3)
            if pytch.key_pressed("s") and self.y_position &gt; -117:
                self.change_y(-3)


class RobotBat(pytch.Sprite):
    Costumes = ["robot-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(215, 0)


class Ball(pytch.Sprite):
    Costumes = ["ball.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(0, 0)

        x_speed = 3
        while True:
            self.change_x(x_speed)

            if self.x_position &gt; 203:
                self.change_x(-x_speed)
                x_speed = -x_speed

            if self.x_position &lt; -203:
                self.change_x(-x_speed)
                x_speed = -x_speed
' data-slug="bounce-Ball-off-Player"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>41</pre></td><td class="linenum"><pre>41</pre></td><td><pre>            if self.x_position &gt; 203:</pre></td></tr><tr><td class="linenum"><pre>42</pre></td><td class="linenum"><pre>42</pre></td><td><pre>                self.change_x(-x_speed)</pre></td></tr><tr><td class="linenum"><pre>43</pre></td><td class="linenum"><pre>43</pre></td><td><pre>                x_speed = -x_speed</pre></td></tr></tbody><tbody class="diff-add" data-added-text="
            if self.x_position &lt; -203:
                self.change_x(-x_speed)
                x_speed = -x_speed
"><tr><td class="linenum"></td><td class="linenum"><pre>44</pre></td><td><pre></pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>45</pre></td><td><pre>            if self.x_position &lt; -203:</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>46</pre></td><td><pre>                self.change_x(-x_speed)</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>47</pre></td><td><pre>                x_speed = -x_speed</pre></td></tr></tbody></table></div></div><p>If you run this now, it looks good but boring.  The ball just bounces
backwards and forwards between the player and the robot.  But!  If you
move the player up or down, you'll see that the ball bounces even it
the player misses it.  We'll fix this next.</p></div><div class="chapter-content"><h2>Bounce properly off the player's bat</h2><p>What we want to do is measure how far up or down on the player's bat
the ball has hit, if it hits the bat at all.  We'll call the centre of
the bat 'zero', with positive positions towards the top of the bat,
and negative positions towards the bottom.  We can work this out by
finding the vertical position — the <em>y</em> coordinate — of the player's
bat, and subtracting that from the ball's <em>y</em> coordinate:</p><div class="patch-container" data-code-as-of-commit='import pytch


class BoingBackground(pytch.Stage):
    Backdrops = ["table.png"]


class PlayerBat(pytch.Sprite):
    Costumes = ["player-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(-215, 0)

        while True:
            if pytch.key_pressed("w") and self.y_position &lt; 117:
                self.change_y(3)
            if pytch.key_pressed("s") and self.y_position &gt; -117:
                self.change_y(-3)


class RobotBat(pytch.Sprite):
    Costumes = ["robot-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(215, 0)


class Ball(pytch.Sprite):
    Costumes = ["ball.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(0, 0)

        x_speed = 3
        while True:
            self.change_x(x_speed)

            if self.x_position &gt; 203:
                self.change_x(-x_speed)
                x_speed = -x_speed

            if self.x_position &lt; -203:
                player_y = PlayerBat.the_original().y_position
                position_on_bat = self.y_position - player_y
                self.change_x(-x_speed)
                x_speed = -x_speed
' data-slug="compute-position-on-Player"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>43</pre></td><td class="linenum"><pre>43</pre></td><td><pre>                x_speed = -x_speed</pre></td></tr><tr><td class="linenum"><pre>44</pre></td><td class="linenum"><pre>44</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>45</pre></td><td class="linenum"><pre>45</pre></td><td><pre>            if self.x_position &lt; -203:</pre></td></tr></tbody><tbody class="diff-add" data-added-text="                player_y = PlayerBat.the_original().y_position
                position_on_bat = self.y_position - player_y
"><tr><td class="linenum"></td><td class="linenum"><pre>46</pre></td><td><pre>                player_y = PlayerBat.the_original().y_position</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>47</pre></td><td><pre>                position_on_bat = self.y_position - player_y</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>46</pre></td><td class="linenum"><pre>48</pre></td><td><pre>                self.change_x(-x_speed)</pre></td></tr><tr><td class="linenum"><pre>47</pre></td><td class="linenum"><pre>49</pre></td><td><pre>                x_speed = -x_speed</pre></td></tr></tbody></table></div></div><p>By experimenting with the '45' in the following code, we can see what
a fair number to use so the ball bounces when it looks like it should
bounce, and misses when it looks like it should miss.  The ball only
bounces if the position on the bat is 'higher than the bottom of the
bat' and also 'lower than the top of the bat':</p><div class="patch-container" data-code-as-of-commit='import pytch


class BoingBackground(pytch.Stage):
    Backdrops = ["table.png"]


class PlayerBat(pytch.Sprite):
    Costumes = ["player-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(-215, 0)

        while True:
            if pytch.key_pressed("w") and self.y_position &lt; 117:
                self.change_y(3)
            if pytch.key_pressed("s") and self.y_position &gt; -117:
                self.change_y(-3)


class RobotBat(pytch.Sprite):
    Costumes = ["robot-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(215, 0)


class Ball(pytch.Sprite):
    Costumes = ["ball.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(0, 0)

        x_speed = 3
        while True:
            self.change_x(x_speed)

            if self.x_position &gt; 203:
                self.change_x(-x_speed)
                x_speed = -x_speed

            if self.x_position &lt; -203:
                player_y = PlayerBat.the_original().y_position
                position_on_bat = self.y_position - player_y
                if (position_on_bat &gt;= -45) and (position_on_bat &lt;= 45):
                    self.change_x(-x_speed)
                    x_speed = -x_speed
' data-slug="check-Player-has-hit-Ball"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>45</pre></td><td class="linenum"><pre>45</pre></td><td><pre>            if self.x_position &lt; -203:</pre></td></tr><tr><td class="linenum"><pre>46</pre></td><td class="linenum"><pre>46</pre></td><td><pre>                player_y = PlayerBat.the_original().y_position</pre></td></tr><tr><td class="linenum"><pre>47</pre></td><td class="linenum"><pre>47</pre></td><td><pre>                position_on_bat = self.y_position - player_y</pre></td></tr></tbody><tbody class="diff-del"><tr><td class="linenum"><pre>48</pre></td><td class="linenum"></td><td><pre>                self.change_x(-x_speed)</pre></td></tr><tr><td class="linenum"><pre>49</pre></td><td class="linenum"></td><td><pre>                x_speed = -x_speed</pre></td></tr></tbody><tbody class="diff-add" data-added-text="                if (position_on_bat &gt;= -45) and (position_on_bat &lt;= 45):
                    self.change_x(-x_speed)
                    x_speed = -x_speed
"><tr><td class="linenum"></td><td class="linenum"><pre>48</pre></td><td><pre>                if (position_on_bat &gt;= -45) and (position_on_bat &lt;= 45):</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>49</pre></td><td><pre>                    self.change_x(-x_speed)</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>50</pre></td><td><pre>                    x_speed = -x_speed</pre></td></tr></tbody></table></div></div><p>This is better.  The ball bounces when it should, but if the player is
too high or too low, the ball sails right past, off to the left.  But
this does not make for an interesting game.</p><p>We'll make the ball bounce off in different directions, depending
where on the bat the player hits it.  If the player hits the ball with
the top of their bat, the ball will bounce off upwards, and similarly
for the bottom of their bat.</p><p>To let us work with this, the ball needs to remember how quickly it's
moving <em>vertically</em>, i.e., in the <em>y</em> direction.  So we add another
local variable, <code>y_speed</code>.  It starts off as zero, because the ball is
moving neither up nor down, just straight across:</p><div class="patch-container" data-code-as-of-commit='import pytch


class BoingBackground(pytch.Stage):
    Backdrops = ["table.png"]


class PlayerBat(pytch.Sprite):
    Costumes = ["player-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(-215, 0)

        while True:
            if pytch.key_pressed("w") and self.y_position &lt; 117:
                self.change_y(3)
            if pytch.key_pressed("s") and self.y_position &gt; -117:
                self.change_y(-3)


class RobotBat(pytch.Sprite):
    Costumes = ["robot-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(215, 0)


class Ball(pytch.Sprite):
    Costumes = ["ball.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(0, 0)

        x_speed = 3
        y_speed = 0
        while True:
            self.change_x(x_speed)

            if self.x_position &gt; 203:
                self.change_x(-x_speed)
                x_speed = -x_speed

            if self.x_position &lt; -203:
                player_y = PlayerBat.the_original().y_position
                position_on_bat = self.y_position - player_y
                if (position_on_bat &gt;= -45) and (position_on_bat &lt;= 45):
                    self.change_x(-x_speed)
                    x_speed = -x_speed
' data-slug="add-Ball-state-y-speed"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>35</pre></td><td class="linenum"><pre>35</pre></td><td><pre>        self.go_to_xy(0, 0)</pre></td></tr><tr><td class="linenum"><pre>36</pre></td><td class="linenum"><pre>36</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>37</pre></td><td class="linenum"><pre>37</pre></td><td><pre>        x_speed = 3</pre></td></tr></tbody><tbody class="diff-add" data-added-text="        y_speed = 0
"><tr><td class="linenum"></td><td class="linenum"><pre>38</pre></td><td><pre>        y_speed = 0</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>38</pre></td><td class="linenum"><pre>39</pre></td><td><pre>        while True:</pre></td></tr><tr><td class="linenum"><pre>39</pre></td><td class="linenum"><pre>40</pre></td><td><pre>            self.change_x(x_speed)</pre></td></tr><tr><td class="linenum"><pre>40</pre></td><td class="linenum"><pre>41</pre></td><td><pre></pre></td></tr></tbody></table></div></div><p>Every step, the ball should change its <em>y</em> position by this amount:</p><div class="patch-container" data-code-as-of-commit='import pytch


class BoingBackground(pytch.Stage):
    Backdrops = ["table.png"]


class PlayerBat(pytch.Sprite):
    Costumes = ["player-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(-215, 0)

        while True:
            if pytch.key_pressed("w") and self.y_position &lt; 117:
                self.change_y(3)
            if pytch.key_pressed("s") and self.y_position &gt; -117:
                self.change_y(-3)


class RobotBat(pytch.Sprite):
    Costumes = ["robot-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(215, 0)


class Ball(pytch.Sprite):
    Costumes = ["ball.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(0, 0)

        x_speed = 3
        y_speed = 0
        while True:
            self.change_x(x_speed)

            if self.x_position &gt; 203:
                self.change_x(-x_speed)
                x_speed = -x_speed

            if self.x_position &lt; -203:
                player_y = PlayerBat.the_original().y_position
                position_on_bat = self.y_position - player_y
                if (position_on_bat &gt;= -45) and (position_on_bat &lt;= 45):
                    self.change_x(-x_speed)
                    x_speed = -x_speed

            self.change_y(y_speed)
' data-slug="change-Ball-y"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>49</pre></td><td class="linenum"><pre>49</pre></td><td><pre>                if (position_on_bat &gt;= -45) and (position_on_bat &lt;= 45):</pre></td></tr><tr><td class="linenum"><pre>50</pre></td><td class="linenum"><pre>50</pre></td><td><pre>                    self.change_x(-x_speed)</pre></td></tr><tr><td class="linenum"><pre>51</pre></td><td class="linenum"><pre>51</pre></td><td><pre>                    x_speed = -x_speed</pre></td></tr></tbody><tbody class="diff-add" data-added-text="
            self.change_y(y_speed)
"><tr><td class="linenum"></td><td class="linenum"><pre>52</pre></td><td><pre></pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>53</pre></td><td><pre>            self.change_y(y_speed)</pre></td></tr></tbody></table></div></div><p>At the moment this makes no difference, because changing something by
zero leaves it alone.</p><p>We can now make the ball fly off in different directions, depending on
where on the bat the player hit it.  We worked out that the 'position
on bat' goes from about <code>-45</code> at the bottom to <code>45</code> at the top.
We'll divide this by ten to get the ball's new <em>y</em>-speed, but ignoring
any remainder by telling Pytch to turn the answer of the division into
an <em>integer</em> (whole number) using <code>int()</code>:</p><div class="patch-container" data-code-as-of-commit='import pytch


class BoingBackground(pytch.Stage):
    Backdrops = ["table.png"]


class PlayerBat(pytch.Sprite):
    Costumes = ["player-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(-215, 0)

        while True:
            if pytch.key_pressed("w") and self.y_position &lt; 117:
                self.change_y(3)
            if pytch.key_pressed("s") and self.y_position &gt; -117:
                self.change_y(-3)


class RobotBat(pytch.Sprite):
    Costumes = ["robot-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(215, 0)


class Ball(pytch.Sprite):
    Costumes = ["ball.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(0, 0)

        x_speed = 3
        y_speed = 0
        while True:
            self.change_x(x_speed)

            if self.x_position &gt; 203:
                self.change_x(-x_speed)
                x_speed = -x_speed

            if self.x_position &lt; -203:
                player_y = PlayerBat.the_original().y_position
                position_on_bat = self.y_position - player_y
                if (position_on_bat &gt;= -45) and (position_on_bat &lt;= 45):
                    y_speed = int(position_on_bat / 10)
                    self.change_x(-x_speed)
                    x_speed = -x_speed

            self.change_y(y_speed)
' data-slug="make-Ball-y-speed-depend-on-Player-position"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>47</pre></td><td class="linenum"><pre>47</pre></td><td><pre>                player_y = PlayerBat.the_original().y_position</pre></td></tr><tr><td class="linenum"><pre>48</pre></td><td class="linenum"><pre>48</pre></td><td><pre>                position_on_bat = self.y_position - player_y</pre></td></tr><tr><td class="linenum"><pre>49</pre></td><td class="linenum"><pre>49</pre></td><td><pre>                if (position_on_bat &gt;= -45) and (position_on_bat &lt;= 45):</pre></td></tr></tbody><tbody class="diff-add" data-added-text="                    y_speed = int(position_on_bat / 10)
"><tr><td class="linenum"></td><td class="linenum"><pre>50</pre></td><td><pre>                    y_speed = int(position_on_bat / 10)</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>50</pre></td><td class="linenum"><pre>51</pre></td><td><pre>                    self.change_x(-x_speed)</pre></td></tr><tr><td class="linenum"><pre>51</pre></td><td class="linenum"><pre>52</pre></td><td><pre>                    x_speed = -x_speed</pre></td></tr><tr><td class="linenum"><pre>52</pre></td><td class="linenum"><pre>53</pre></td><td><pre></pre></td></tr></tbody></table></div></div><p>If you try this now, you can check that the ball bounces off the
player's bat as it should.  But the ball then just keeps flying off
the top or bottom of the screen.</p></div><div class="chapter-content"><h2>Bounce the ball off the top and bottom of the court</h2><p>We can tell if the ball has gone too high or too low by comparing its
<em>y</em> coordinate to numbers chosen by experiment.  If it has gone too
high or too low, we undo the last <em>y</em> change, and make the <em>y</em>-speed
be the opposite of what it was:</p><div class="patch-container" data-code-as-of-commit='import pytch


class BoingBackground(pytch.Stage):
    Backdrops = ["table.png"]


class PlayerBat(pytch.Sprite):
    Costumes = ["player-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(-215, 0)

        while True:
            if pytch.key_pressed("w") and self.y_position &lt; 117:
                self.change_y(3)
            if pytch.key_pressed("s") and self.y_position &gt; -117:
                self.change_y(-3)


class RobotBat(pytch.Sprite):
    Costumes = ["robot-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(215, 0)


class Ball(pytch.Sprite):
    Costumes = ["ball.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(0, 0)

        x_speed = 3
        y_speed = 0
        while True:
            self.change_x(x_speed)

            if self.x_position &gt; 203:
                self.change_x(-x_speed)
                x_speed = -x_speed

            if self.x_position &lt; -203:
                player_y = PlayerBat.the_original().y_position
                position_on_bat = self.y_position - player_y
                if (position_on_bat &gt;= -45) and (position_on_bat &lt;= 45):
                    y_speed = int(position_on_bat / 10)
                    self.change_x(-x_speed)
                    x_speed = -x_speed

            self.change_y(y_speed)

            if self.y_position &gt; 158 or self.y_position &lt; -158:
                self.change_y(-y_speed)
                y_speed = -y_speed
' data-slug="make-Ball-bounce-vertically"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>52</pre></td><td class="linenum"><pre>52</pre></td><td><pre>                    x_speed = -x_speed</pre></td></tr><tr><td class="linenum"><pre>53</pre></td><td class="linenum"><pre>53</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>54</pre></td><td class="linenum"><pre>54</pre></td><td><pre>            self.change_y(y_speed)</pre></td></tr></tbody><tbody class="diff-add" data-added-text="
            if self.y_position &gt; 158 or self.y_position &lt; -158:
                self.change_y(-y_speed)
                y_speed = -y_speed
"><tr><td class="linenum"></td><td class="linenum"><pre>55</pre></td><td><pre></pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>56</pre></td><td><pre>            if self.y_position &gt; 158 or self.y_position &lt; -158:</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>57</pre></td><td><pre>                self.change_y(-y_speed)</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>58</pre></td><td><pre>                y_speed = -y_speed</pre></td></tr></tbody></table></div></div><p>If you play the game now, it sort of works, but there are two obvious
problems:</p><ul>
<li>
<p>The ball keeps going past the player's bat if you miss and then
  after a short while mysteriously re-appears.</p>
</li>
<li>
<p>The robot player never moves but still the ball bounces off the
  right-hand edge of the screen.</p>
</li>
</ul><p>We'll fix these things next.</p></div><div class="chapter-content"><h2>End the game if the player misses</h2><p>The code we added to bounce the ball off the player's bat checked if
the <em>position on the bat</em> was not too high or too low, and then
bounced the ball if it was OK.  But it did nothing if the ball <em>was</em>
too high or too low.  We need to add an <code>else</code> clause, saying that if
the player misses, that's the end of the game.  The ball should hide,
and we <code>break</code> out of the <code>while True</code> loop, to finish the game:</p><div class="patch-container" data-code-as-of-commit='import pytch


class BoingBackground(pytch.Stage):
    Backdrops = ["table.png"]


class PlayerBat(pytch.Sprite):
    Costumes = ["player-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(-215, 0)

        while True:
            if pytch.key_pressed("w") and self.y_position &lt; 117:
                self.change_y(3)
            if pytch.key_pressed("s") and self.y_position &gt; -117:
                self.change_y(-3)


class RobotBat(pytch.Sprite):
    Costumes = ["robot-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(215, 0)


class Ball(pytch.Sprite):
    Costumes = ["ball.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(0, 0)

        x_speed = 3
        y_speed = 0
        while True:
            self.change_x(x_speed)

            if self.x_position &gt; 203:
                self.change_x(-x_speed)
                x_speed = -x_speed

            if self.x_position &lt; -203:
                player_y = PlayerBat.the_original().y_position
                position_on_bat = self.y_position - player_y
                if (position_on_bat &gt;= -45) and (position_on_bat &lt;= 45):
                    y_speed = int(position_on_bat / 10)
                    self.change_x(-x_speed)
                    x_speed = -x_speed
                else:
                    self.hide()
                    break

            self.change_y(y_speed)

            if self.y_position &gt; 158 or self.y_position &lt; -158:
                self.change_y(-y_speed)
                y_speed = -y_speed
' data-slug="hide-Ball-if-Player-misses"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>50</pre></td><td class="linenum"><pre>50</pre></td><td><pre>                    y_speed = int(position_on_bat / 10)</pre></td></tr><tr><td class="linenum"><pre>51</pre></td><td class="linenum"><pre>51</pre></td><td><pre>                    self.change_x(-x_speed)</pre></td></tr><tr><td class="linenum"><pre>52</pre></td><td class="linenum"><pre>52</pre></td><td><pre>                    x_speed = -x_speed</pre></td></tr></tbody><tbody class="diff-add" data-added-text="                else:
                    self.hide()
                    break
"><tr><td class="linenum"></td><td class="linenum"><pre>53</pre></td><td><pre>                else:</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>54</pre></td><td><pre>                    self.hide()</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>55</pre></td><td><pre>                    break</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>53</pre></td><td class="linenum"><pre>56</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>54</pre></td><td class="linenum"><pre>57</pre></td><td><pre>            self.change_y(y_speed)</pre></td></tr><tr><td class="linenum"><pre>55</pre></td><td class="linenum"><pre>58</pre></td><td><pre></pre></td></tr></tbody></table></div></div><p>This is better, but looks odd because the ball just vanishes.  We can
fix this by moving the ball for another few steps once we know the
player has missed it:</p><div class="patch-container" data-code-as-of-commit='import pytch


class BoingBackground(pytch.Stage):
    Backdrops = ["table.png"]


class PlayerBat(pytch.Sprite):
    Costumes = ["player-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(-215, 0)

        while True:
            if pytch.key_pressed("w") and self.y_position &lt; 117:
                self.change_y(3)
            if pytch.key_pressed("s") and self.y_position &gt; -117:
                self.change_y(-3)


class RobotBat(pytch.Sprite):
    Costumes = ["robot-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(215, 0)


class Ball(pytch.Sprite):
    Costumes = ["ball.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(0, 0)

        x_speed = 3
        y_speed = 0
        while True:
            self.change_x(x_speed)

            if self.x_position &gt; 203:
                self.change_x(-x_speed)
                x_speed = -x_speed

            if self.x_position &lt; -203:
                player_y = PlayerBat.the_original().y_position
                position_on_bat = self.y_position - player_y
                if (position_on_bat &gt;= -45) and (position_on_bat &lt;= 45):
                    y_speed = int(position_on_bat / 10)
                    self.change_x(-x_speed)
                    x_speed = -x_speed
                else:
                    for i in range(10):
                        self.change_x(x_speed)
                        self.change_y(y_speed)
                    self.hide()
                    break

            self.change_y(y_speed)

            if self.y_position &gt; 158 or self.y_position &lt; -158:
                self.change_y(-y_speed)
                y_speed = -y_speed
' data-slug="continue-Ball-briefly-if-Player-misses"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>51</pre></td><td class="linenum"><pre>51</pre></td><td><pre>                    self.change_x(-x_speed)</pre></td></tr><tr><td class="linenum"><pre>52</pre></td><td class="linenum"><pre>52</pre></td><td><pre>                    x_speed = -x_speed</pre></td></tr><tr><td class="linenum"><pre>53</pre></td><td class="linenum"><pre>53</pre></td><td><pre>                else:</pre></td></tr></tbody><tbody class="diff-add" data-added-text="                    for i in range(10):
                        self.change_x(x_speed)
                        self.change_y(y_speed)
"><tr><td class="linenum"></td><td class="linenum"><pre>54</pre></td><td><pre>                    for i in range(10):</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>55</pre></td><td><pre>                        self.change_x(x_speed)</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>56</pre></td><td><pre>                        self.change_y(y_speed)</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>54</pre></td><td class="linenum"><pre>57</pre></td><td><pre>                    self.hide()</pre></td></tr><tr><td class="linenum"><pre>55</pre></td><td class="linenum"><pre>58</pre></td><td><pre>                    break</pre></td></tr><tr><td class="linenum"><pre>56</pre></td><td class="linenum"><pre>59</pre></td><td><pre></pre></td></tr></tbody></table></div></div><p>(This still isn't quite right if the ball should bounce vertically,
but we'll ignore that.)</p></div><div class="chapter-content"><h2>Move the robot's bat automatically</h2><p>Returning to the robot player, at the moment it just moves to the
centre at the start of the game and stays there.  We want it to then
keep its vertical position (<em>y</em> coordinate) matching the ball's.  This
will make it follow the ball up and down:</p><div class="patch-container" data-code-as-of-commit='import pytch


class BoingBackground(pytch.Stage):
    Backdrops = ["table.png"]


class PlayerBat(pytch.Sprite):
    Costumes = ["player-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(-215, 0)

        while True:
            if pytch.key_pressed("w") and self.y_position &lt; 117:
                self.change_y(3)
            if pytch.key_pressed("s") and self.y_position &gt; -117:
                self.change_y(-3)


class RobotBat(pytch.Sprite):
    Costumes = ["robot-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(215, 0)

        while True:
            target_y = Ball.the_original().y_position
            self.set_y(target_y)


class Ball(pytch.Sprite):
    Costumes = ["ball.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(0, 0)

        x_speed = 3
        y_speed = 0
        while True:
            self.change_x(x_speed)

            if self.x_position &gt; 203:
                self.change_x(-x_speed)
                x_speed = -x_speed

            if self.x_position &lt; -203:
                player_y = PlayerBat.the_original().y_position
                position_on_bat = self.y_position - player_y
                if (position_on_bat &gt;= -45) and (position_on_bat &lt;= 45):
                    y_speed = int(position_on_bat / 10)
                    self.change_x(-x_speed)
                    x_speed = -x_speed
                else:
                    for i in range(10):
                        self.change_x(x_speed)
                        self.change_y(y_speed)
                    self.hide()
                    break

            self.change_y(y_speed)

            if self.y_position &gt; 158 or self.y_position &lt; -158:
                self.change_y(-y_speed)
                y_speed = -y_speed
' data-slug="make-Robot-track-Ball"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>26</pre></td><td class="linenum"><pre>26</pre></td><td><pre>    def play(self):</pre></td></tr><tr><td class="linenum"><pre>27</pre></td><td class="linenum"><pre>27</pre></td><td><pre>        self.go_to_xy(215, 0)</pre></td></tr><tr><td class="linenum"><pre>28</pre></td><td class="linenum"><pre>28</pre></td><td><pre></pre></td></tr></tbody><tbody class="diff-add" data-added-text="        while True:
            target_y = Ball.the_original().y_position
            self.set_y(target_y)

"><tr><td class="linenum"></td><td class="linenum"><pre>29</pre></td><td><pre>        while True:</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>30</pre></td><td><pre>            target_y = Ball.the_original().y_position</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>31</pre></td><td><pre>            self.set_y(target_y)</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>32</pre></td><td><pre></pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>29</pre></td><td class="linenum"><pre>33</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>30</pre></td><td class="linenum"><pre>34</pre></td><td><pre>class Ball(pytch.Sprite):</pre></td></tr><tr><td class="linenum"><pre>31</pre></td><td class="linenum"><pre>35</pre></td><td><pre>    Costumes = ["ball.png"]</pre></td></tr></tbody></table></div></div><p>This is much better, but still not quite right.  The robot can go off
the top of the court or off the bottom.  If moving to the ball's
position has taken the bat off the top of the court, we set the bat to
be at the top of the court instead.  And similarly for the bottom:</p><div class="patch-container" data-code-as-of-commit='import pytch


class BoingBackground(pytch.Stage):
    Backdrops = ["table.png"]


class PlayerBat(pytch.Sprite):
    Costumes = ["player-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(-215, 0)

        while True:
            if pytch.key_pressed("w") and self.y_position &lt; 117:
                self.change_y(3)
            if pytch.key_pressed("s") and self.y_position &gt; -117:
                self.change_y(-3)


class RobotBat(pytch.Sprite):
    Costumes = ["robot-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(215, 0)

        while True:
            target_y = Ball.the_original().y_position
            if target_y &lt; -117:
                target_y = -117
            if target_y &gt; 117:
                target_y = 117
            self.set_y(target_y)


class Ball(pytch.Sprite):
    Costumes = ["ball.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(0, 0)

        x_speed = 3
        y_speed = 0
        while True:
            self.change_x(x_speed)

            if self.x_position &gt; 203:
                self.change_x(-x_speed)
                x_speed = -x_speed

            if self.x_position &lt; -203:
                player_y = PlayerBat.the_original().y_position
                position_on_bat = self.y_position - player_y
                if (position_on_bat &gt;= -45) and (position_on_bat &lt;= 45):
                    y_speed = int(position_on_bat / 10)
                    self.change_x(-x_speed)
                    x_speed = -x_speed
                else:
                    for i in range(10):
                        self.change_x(x_speed)
                        self.change_y(y_speed)
                    self.hide()
                    break

            self.change_y(y_speed)

            if self.y_position &gt; 158 or self.y_position &lt; -158:
                self.change_y(-y_speed)
                y_speed = -y_speed
' data-slug="ensure-Robot-stays-in-court"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>28</pre></td><td class="linenum"><pre>28</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>29</pre></td><td class="linenum"><pre>29</pre></td><td><pre>        while True:</pre></td></tr><tr><td class="linenum"><pre>30</pre></td><td class="linenum"><pre>30</pre></td><td><pre>            target_y = Ball.the_original().y_position</pre></td></tr></tbody><tbody class="diff-add" data-added-text="            if target_y &lt; -117:
                target_y = -117
            if target_y &gt; 117:
                target_y = 117
"><tr><td class="linenum"></td><td class="linenum"><pre>31</pre></td><td><pre>            if target_y &lt; -117:</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>32</pre></td><td><pre>                target_y = -117</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>33</pre></td><td><pre>            if target_y &gt; 117:</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>34</pre></td><td><pre>                target_y = 117</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>31</pre></td><td class="linenum"><pre>35</pre></td><td><pre>            self.set_y(target_y)</pre></td></tr><tr><td class="linenum"><pre>32</pre></td><td class="linenum"><pre>36</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>33</pre></td><td class="linenum"><pre>37</pre></td><td><pre></pre></td></tr></tbody></table></div></div></div><div class="chapter-content"><h2>Make some noise</h2><p>We want to bring in some sounds for the game:</p><ul>
<li>
<p>Different bounce noises for bouncing off a bat compared to the top
  or bottom of the court.</p>
</li>
<li>
<p>Make a sound when the player loses.  (The robot never loses!)</p>
</li>
</ul><p>We define these in a similar way to costumes.  We say what the
<code>Sounds</code> for a sprite are.  We say which filename each sound comes
from:</p><div class="patch-container" data-code-as-of-commit='import pytch


class BoingBackground(pytch.Stage):
    Backdrops = ["table.png"]


class PlayerBat(pytch.Sprite):
    Costumes = ["player-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(-215, 0)

        while True:
            if pytch.key_pressed("w") and self.y_position &lt; 117:
                self.change_y(3)
            if pytch.key_pressed("s") and self.y_position &gt; -117:
                self.change_y(-3)


class RobotBat(pytch.Sprite):
    Costumes = ["robot-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(215, 0)

        while True:
            target_y = Ball.the_original().y_position
            if target_y &lt; -117:
                target_y = -117
            if target_y &gt; 117:
                target_y = 117
            self.set_y(target_y)


class Ball(pytch.Sprite):
    Costumes = ["ball.png"]
    Sounds = ["hit.mp3", "bounce.mp3", "lost.mp3"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(0, 0)

        x_speed = 3
        y_speed = 0
        while True:
            self.change_x(x_speed)

            if self.x_position &gt; 203:
                self.change_x(-x_speed)
                x_speed = -x_speed

            if self.x_position &lt; -203:
                player_y = PlayerBat.the_original().y_position
                position_on_bat = self.y_position - player_y
                if (position_on_bat &gt;= -45) and (position_on_bat &lt;= 45):
                    y_speed = int(position_on_bat / 10)
                    self.change_x(-x_speed)
                    x_speed = -x_speed
                else:
                    for i in range(10):
                        self.change_x(x_speed)
                        self.change_y(y_speed)
                    self.hide()
                    break

            self.change_y(y_speed)

            if self.y_position &gt; 158 or self.y_position &lt; -158:
                self.change_y(-y_speed)
                y_speed = -y_speed
' data-slug="define-Sounds-for-Ball"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>37</pre></td><td class="linenum"><pre>37</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>38</pre></td><td class="linenum"><pre>38</pre></td><td><pre>class Ball(pytch.Sprite):</pre></td></tr><tr><td class="linenum"><pre>39</pre></td><td class="linenum"><pre>39</pre></td><td><pre>    Costumes = ["ball.png"]</pre></td></tr></tbody><tbody class="diff-add" data-added-text='    Sounds = ["hit.mp3", "bounce.mp3", "lost.mp3"]
'><tr><td class="linenum"></td><td class="linenum"><pre>40</pre></td><td><pre>    Sounds = ["hit.mp3", "bounce.mp3", "lost.mp3"]</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>40</pre></td><td class="linenum"><pre>41</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>41</pre></td><td class="linenum"><pre>42</pre></td><td><pre>    @pytch.when_green_flag_clicked</pre></td></tr><tr><td class="linenum"><pre>42</pre></td><td class="linenum"><pre>43</pre></td><td><pre>    def play(self):</pre></td></tr></tbody></table></div></div><p>To make the 'a bat hit the ball' sound, we start the <code>hit</code> sound just
after changing the ball's <code>x_speed</code>, which we do here for if it hits
the robot's bat:</p><div class="patch-container" data-code-as-of-commit='import pytch


class BoingBackground(pytch.Stage):
    Backdrops = ["table.png"]


class PlayerBat(pytch.Sprite):
    Costumes = ["player-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(-215, 0)

        while True:
            if pytch.key_pressed("w") and self.y_position &lt; 117:
                self.change_y(3)
            if pytch.key_pressed("s") and self.y_position &gt; -117:
                self.change_y(-3)


class RobotBat(pytch.Sprite):
    Costumes = ["robot-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(215, 0)

        while True:
            target_y = Ball.the_original().y_position
            if target_y &lt; -117:
                target_y = -117
            if target_y &gt; 117:
                target_y = 117
            self.set_y(target_y)


class Ball(pytch.Sprite):
    Costumes = ["ball.png"]
    Sounds = ["hit.mp3", "bounce.mp3", "lost.mp3"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(0, 0)

        x_speed = 3
        y_speed = 0
        while True:
            self.change_x(x_speed)

            if self.x_position &gt; 203:
                self.change_x(-x_speed)
                x_speed = -x_speed
                self.start_sound("hit")

            if self.x_position &lt; -203:
                player_y = PlayerBat.the_original().y_position
                position_on_bat = self.y_position - player_y
                if (position_on_bat &gt;= -45) and (position_on_bat &lt;= 45):
                    y_speed = int(position_on_bat / 10)
                    self.change_x(-x_speed)
                    x_speed = -x_speed
                else:
                    for i in range(10):
                        self.change_x(x_speed)
                        self.change_y(y_speed)
                    self.hide()
                    break

            self.change_y(y_speed)

            if self.y_position &gt; 158 or self.y_position &lt; -158:
                self.change_y(-y_speed)
                y_speed = -y_speed
' data-slug="play-hit-sound-for-Robot-hit"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>51</pre></td><td class="linenum"><pre>51</pre></td><td><pre>            if self.x_position &gt; 203:</pre></td></tr><tr><td class="linenum"><pre>52</pre></td><td class="linenum"><pre>52</pre></td><td><pre>                self.change_x(-x_speed)</pre></td></tr><tr><td class="linenum"><pre>53</pre></td><td class="linenum"><pre>53</pre></td><td><pre>                x_speed = -x_speed</pre></td></tr></tbody><tbody class="diff-add" data-added-text='                self.start_sound("hit")
'><tr><td class="linenum"></td><td class="linenum"><pre>54</pre></td><td><pre>                self.start_sound("hit")</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>54</pre></td><td class="linenum"><pre>55</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>55</pre></td><td class="linenum"><pre>56</pre></td><td><pre>            if self.x_position &lt; -203:</pre></td></tr><tr><td class="linenum"><pre>56</pre></td><td class="linenum"><pre>57</pre></td><td><pre>                player_y = PlayerBat.the_original().y_position</pre></td></tr></tbody></table></div></div><p>and here if the ball has bounced off the player's bat:</p><div class="patch-container" data-code-as-of-commit='import pytch


class BoingBackground(pytch.Stage):
    Backdrops = ["table.png"]


class PlayerBat(pytch.Sprite):
    Costumes = ["player-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(-215, 0)

        while True:
            if pytch.key_pressed("w") and self.y_position &lt; 117:
                self.change_y(3)
            if pytch.key_pressed("s") and self.y_position &gt; -117:
                self.change_y(-3)


class RobotBat(pytch.Sprite):
    Costumes = ["robot-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(215, 0)

        while True:
            target_y = Ball.the_original().y_position
            if target_y &lt; -117:
                target_y = -117
            if target_y &gt; 117:
                target_y = 117
            self.set_y(target_y)


class Ball(pytch.Sprite):
    Costumes = ["ball.png"]
    Sounds = ["hit.mp3", "bounce.mp3", "lost.mp3"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(0, 0)

        x_speed = 3
        y_speed = 0
        while True:
            self.change_x(x_speed)

            if self.x_position &gt; 203:
                self.change_x(-x_speed)
                x_speed = -x_speed
                self.start_sound("hit")

            if self.x_position &lt; -203:
                player_y = PlayerBat.the_original().y_position
                position_on_bat = self.y_position - player_y
                if (position_on_bat &gt;= -45) and (position_on_bat &lt;= 45):
                    y_speed = int(position_on_bat / 10)
                    self.change_x(-x_speed)
                    x_speed = -x_speed
                    self.start_sound("hit")
                else:
                    for i in range(10):
                        self.change_x(x_speed)
                        self.change_y(y_speed)
                    self.hide()
                    break

            self.change_y(y_speed)

            if self.y_position &gt; 158 or self.y_position &lt; -158:
                self.change_y(-y_speed)
                y_speed = -y_speed
' data-slug="play-hit-sound-for-Player-hit"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>60</pre></td><td class="linenum"><pre>60</pre></td><td><pre>                    y_speed = int(position_on_bat / 10)</pre></td></tr><tr><td class="linenum"><pre>61</pre></td><td class="linenum"><pre>61</pre></td><td><pre>                    self.change_x(-x_speed)</pre></td></tr><tr><td class="linenum"><pre>62</pre></td><td class="linenum"><pre>62</pre></td><td><pre>                    x_speed = -x_speed</pre></td></tr></tbody><tbody class="diff-add" data-added-text='                    self.start_sound("hit")
'><tr><td class="linenum"></td><td class="linenum"><pre>63</pre></td><td><pre>                    self.start_sound("hit")</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>63</pre></td><td class="linenum"><pre>64</pre></td><td><pre>                else:</pre></td></tr><tr><td class="linenum"><pre>64</pre></td><td class="linenum"><pre>65</pre></td><td><pre>                    for i in range(10):</pre></td></tr><tr><td class="linenum"><pre>65</pre></td><td class="linenum"><pre>66</pre></td><td><pre>                        self.change_x(x_speed)</pre></td></tr></tbody></table></div></div><p>If the ball bounces off the top or bottom of the court, we start the
<code>bounce</code> sound straight after flipping the ball's <code>y_speed</code>:</p><div class="patch-container" data-code-as-of-commit='import pytch


class BoingBackground(pytch.Stage):
    Backdrops = ["table.png"]


class PlayerBat(pytch.Sprite):
    Costumes = ["player-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(-215, 0)

        while True:
            if pytch.key_pressed("w") and self.y_position &lt; 117:
                self.change_y(3)
            if pytch.key_pressed("s") and self.y_position &gt; -117:
                self.change_y(-3)


class RobotBat(pytch.Sprite):
    Costumes = ["robot-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(215, 0)

        while True:
            target_y = Ball.the_original().y_position
            if target_y &lt; -117:
                target_y = -117
            if target_y &gt; 117:
                target_y = 117
            self.set_y(target_y)


class Ball(pytch.Sprite):
    Costumes = ["ball.png"]
    Sounds = ["hit.mp3", "bounce.mp3", "lost.mp3"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(0, 0)

        x_speed = 3
        y_speed = 0
        while True:
            self.change_x(x_speed)

            if self.x_position &gt; 203:
                self.change_x(-x_speed)
                x_speed = -x_speed
                self.start_sound("hit")

            if self.x_position &lt; -203:
                player_y = PlayerBat.the_original().y_position
                position_on_bat = self.y_position - player_y
                if (position_on_bat &gt;= -45) and (position_on_bat &lt;= 45):
                    y_speed = int(position_on_bat / 10)
                    self.change_x(-x_speed)
                    x_speed = -x_speed
                    self.start_sound("hit")
                else:
                    for i in range(10):
                        self.change_x(x_speed)
                        self.change_y(y_speed)
                    self.hide()
                    break

            self.change_y(y_speed)

            if self.y_position &gt; 158 or self.y_position &lt; -158:
                self.change_y(-y_speed)
                y_speed = -y_speed
                self.start_sound("bounce")
' data-slug="play-bounce-sound"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>73</pre></td><td class="linenum"><pre>73</pre></td><td><pre>            if self.y_position &gt; 158 or self.y_position &lt; -158:</pre></td></tr><tr><td class="linenum"><pre>74</pre></td><td class="linenum"><pre>74</pre></td><td><pre>                self.change_y(-y_speed)</pre></td></tr><tr><td class="linenum"><pre>75</pre></td><td class="linenum"><pre>75</pre></td><td><pre>                y_speed = -y_speed</pre></td></tr></tbody><tbody class="diff-add" data-added-text='                self.start_sound("bounce")
'><tr><td class="linenum"></td><td class="linenum"><pre>76</pre></td><td><pre>                self.start_sound("bounce")</pre></td></tr></tbody></table></div></div><p>And we can start the <code>lost</code> sound once the ball has gone past the
player's bat and hidden itself:</p><div class="patch-container" data-code-as-of-commit='import pytch


class BoingBackground(pytch.Stage):
    Backdrops = ["table.png"]


class PlayerBat(pytch.Sprite):
    Costumes = ["player-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(-215, 0)

        while True:
            if pytch.key_pressed("w") and self.y_position &lt; 117:
                self.change_y(3)
            if pytch.key_pressed("s") and self.y_position &gt; -117:
                self.change_y(-3)


class RobotBat(pytch.Sprite):
    Costumes = ["robot-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(215, 0)

        while True:
            target_y = Ball.the_original().y_position
            if target_y &lt; -117:
                target_y = -117
            if target_y &gt; 117:
                target_y = 117
            self.set_y(target_y)


class Ball(pytch.Sprite):
    Costumes = ["ball.png"]
    Sounds = ["hit.mp3", "bounce.mp3", "lost.mp3"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(0, 0)

        x_speed = 3
        y_speed = 0
        while True:
            self.change_x(x_speed)

            if self.x_position &gt; 203:
                self.change_x(-x_speed)
                x_speed = -x_speed
                self.start_sound("hit")

            if self.x_position &lt; -203:
                player_y = PlayerBat.the_original().y_position
                position_on_bat = self.y_position - player_y
                if (position_on_bat &gt;= -45) and (position_on_bat &lt;= 45):
                    y_speed = int(position_on_bat / 10)
                    self.change_x(-x_speed)
                    x_speed = -x_speed
                    self.start_sound("hit")
                else:
                    for i in range(10):
                        self.change_x(x_speed)
                        self.change_y(y_speed)
                    self.hide()
                    self.start_sound("lost")
                    break

            self.change_y(y_speed)

            if self.y_position &gt; 158 or self.y_position &lt; -158:
                self.change_y(-y_speed)
                y_speed = -y_speed
                self.start_sound("bounce")
' data-slug="play-lost-sound"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>66</pre></td><td class="linenum"><pre>66</pre></td><td><pre>                        self.change_x(x_speed)</pre></td></tr><tr><td class="linenum"><pre>67</pre></td><td class="linenum"><pre>67</pre></td><td><pre>                        self.change_y(y_speed)</pre></td></tr><tr><td class="linenum"><pre>68</pre></td><td class="linenum"><pre>68</pre></td><td><pre>                    self.hide()</pre></td></tr></tbody><tbody class="diff-add" data-added-text='                    self.start_sound("lost")
'><tr><td class="linenum"></td><td class="linenum"><pre>69</pre></td><td><pre>                    self.start_sound("lost")</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>69</pre></td><td class="linenum"><pre>70</pre></td><td><pre>                    break</pre></td></tr><tr><td class="linenum"><pre>70</pre></td><td class="linenum"><pre>71</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>71</pre></td><td class="linenum"><pre>72</pre></td><td><pre>            self.change_y(y_speed)</pre></td></tr></tbody></table></div></div></div><div class="chapter-content"><h2>Add effects when a bat hits the ball</h2><p>To make the game look better, we'll add a flash effect when either the
player or the robots hits the ball.  We'll need to add a costume to
the player bat Sprite:</p><div class="patch-container" data-code-as-of-commit='import pytch


class BoingBackground(pytch.Stage):
    Backdrops = ["table.png"]


class PlayerBat(pytch.Sprite):
    Costumes = ["player-normal.png", "player-flash.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(-215, 0)

        while True:
            if pytch.key_pressed("w") and self.y_position &lt; 117:
                self.change_y(3)
            if pytch.key_pressed("s") and self.y_position &gt; -117:
                self.change_y(-3)


class RobotBat(pytch.Sprite):
    Costumes = ["robot-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(215, 0)

        while True:
            target_y = Ball.the_original().y_position
            if target_y &lt; -117:
                target_y = -117
            if target_y &gt; 117:
                target_y = 117
            self.set_y(target_y)


class Ball(pytch.Sprite):
    Costumes = ["ball.png"]
    Sounds = ["hit.mp3", "bounce.mp3", "lost.mp3"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(0, 0)

        x_speed = 3
        y_speed = 0
        while True:
            self.change_x(x_speed)

            if self.x_position &gt; 203:
                self.change_x(-x_speed)
                x_speed = -x_speed
                self.start_sound("hit")

            if self.x_position &lt; -203:
                player_y = PlayerBat.the_original().y_position
                position_on_bat = self.y_position - player_y
                if (position_on_bat &gt;= -45) and (position_on_bat &lt;= 45):
                    y_speed = int(position_on_bat / 10)
                    self.change_x(-x_speed)
                    x_speed = -x_speed
                    self.start_sound("hit")
                else:
                    for i in range(10):
                        self.change_x(x_speed)
                        self.change_y(y_speed)
                    self.hide()
                    self.start_sound("lost")
                    break

            self.change_y(y_speed)

            if self.y_position &gt; 158 or self.y_position &lt; -158:
                self.change_y(-y_speed)
                y_speed = -y_speed
                self.start_sound("bounce")
' data-slug="declare-Player-hit-flash-costume"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>6</pre></td><td class="linenum"><pre>6</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>7</pre></td><td class="linenum"><pre>7</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>8</pre></td><td class="linenum"><pre>8</pre></td><td><pre>class PlayerBat(pytch.Sprite):</pre></td></tr></tbody><tbody class="diff-del"><tr><td class="linenum"><pre>9</pre></td><td class="linenum"></td><td><pre>    Costumes = ["player-normal.png"]</pre></td></tr></tbody><tbody class="diff-add" data-added-text='    Costumes = ["player-normal.png", "player-flash.png"]
'><tr><td class="linenum"></td><td class="linenum"><pre>9</pre></td><td><pre>    Costumes = ["player-normal.png", "player-flash.png"]</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>10</pre></td><td class="linenum"><pre>10</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>11</pre></td><td class="linenum"><pre>11</pre></td><td><pre>    @pytch.when_green_flag_clicked</pre></td></tr><tr><td class="linenum"><pre>12</pre></td><td class="linenum"><pre>12</pre></td><td><pre>    def play(self):</pre></td></tr></tbody></table></div></div><p>Next we say how we want the flash to happen.  We want to switch to the
<code>hit-flash</code> costume, wait a short time, then switch back to <code>normal</code>.
We'll do this when the player's bat sprite receives a message
<code>player-hit</code>:</p><div class="patch-container" data-code-as-of-commit='import pytch


class BoingBackground(pytch.Stage):
    Backdrops = ["table.png"]


class PlayerBat(pytch.Sprite):
    Costumes = ["player-normal.png", "player-flash.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(-215, 0)

        while True:
            if pytch.key_pressed("w") and self.y_position &lt; 117:
                self.change_y(3)
            if pytch.key_pressed("s") and self.y_position &gt; -117:
                self.change_y(-3)

    @pytch.when_I_receive("player-hit")
    def flash_briefly(self):
        self.switch_costume("player-flash")
        pytch.wait_seconds(0.1)
        self.switch_costume("player-normal")


class RobotBat(pytch.Sprite):
    Costumes = ["robot-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(215, 0)

        while True:
            target_y = Ball.the_original().y_position
            if target_y &lt; -117:
                target_y = -117
            if target_y &gt; 117:
                target_y = 117
            self.set_y(target_y)


class Ball(pytch.Sprite):
    Costumes = ["ball.png"]
    Sounds = ["hit.mp3", "bounce.mp3", "lost.mp3"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(0, 0)

        x_speed = 3
        y_speed = 0
        while True:
            self.change_x(x_speed)

            if self.x_position &gt; 203:
                self.change_x(-x_speed)
                x_speed = -x_speed
                self.start_sound("hit")

            if self.x_position &lt; -203:
                player_y = PlayerBat.the_original().y_position
                position_on_bat = self.y_position - player_y
                if (position_on_bat &gt;= -45) and (position_on_bat &lt;= 45):
                    y_speed = int(position_on_bat / 10)
                    self.change_x(-x_speed)
                    x_speed = -x_speed
                    self.start_sound("hit")
                else:
                    for i in range(10):
                        self.change_x(x_speed)
                        self.change_y(y_speed)
                    self.hide()
                    self.start_sound("lost")
                    break

            self.change_y(y_speed)

            if self.y_position &gt; 158 or self.y_position &lt; -158:
                self.change_y(-y_speed)
                y_speed = -y_speed
                self.start_sound("bounce")
' data-slug="define-Player-hit-handler"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>18</pre></td><td class="linenum"><pre>18</pre></td><td><pre>            if pytch.key_pressed("s") and self.y_position &gt; -117:</pre></td></tr><tr><td class="linenum"><pre>19</pre></td><td class="linenum"><pre>19</pre></td><td><pre>                self.change_y(-3)</pre></td></tr><tr><td class="linenum"><pre>20</pre></td><td class="linenum"><pre>20</pre></td><td><pre></pre></td></tr></tbody><tbody class="diff-add" data-added-text='    @pytch.when_I_receive("player-hit")
    def flash_briefly(self):
        self.switch_costume("player-flash")
        pytch.wait_seconds(0.1)
        self.switch_costume("player-normal")

'><tr><td class="linenum"></td><td class="linenum"><pre>21</pre></td><td><pre>    @pytch.when_I_receive("player-hit")</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>22</pre></td><td><pre>    def flash_briefly(self):</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>23</pre></td><td><pre>        self.switch_costume("player-flash")</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>24</pre></td><td><pre>        pytch.wait_seconds(0.1)</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>25</pre></td><td><pre>        self.switch_costume("player-normal")</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>26</pre></td><td><pre></pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>21</pre></td><td class="linenum"><pre>27</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>22</pre></td><td class="linenum"><pre>28</pre></td><td><pre>class RobotBat(pytch.Sprite):</pre></td></tr><tr><td class="linenum"><pre>23</pre></td><td class="linenum"><pre>29</pre></td><td><pre>    Costumes = ["robot-normal.png"]</pre></td></tr></tbody></table></div></div><p>To make this actually happen, we want to broadcast that message when
the ball bounces off the  player's bat:</p><div class="patch-container" data-code-as-of-commit='import pytch


class BoingBackground(pytch.Stage):
    Backdrops = ["table.png"]


class PlayerBat(pytch.Sprite):
    Costumes = ["player-normal.png", "player-flash.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(-215, 0)

        while True:
            if pytch.key_pressed("w") and self.y_position &lt; 117:
                self.change_y(3)
            if pytch.key_pressed("s") and self.y_position &gt; -117:
                self.change_y(-3)

    @pytch.when_I_receive("player-hit")
    def flash_briefly(self):
        self.switch_costume("player-flash")
        pytch.wait_seconds(0.1)
        self.switch_costume("player-normal")


class RobotBat(pytch.Sprite):
    Costumes = ["robot-normal.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(215, 0)

        while True:
            target_y = Ball.the_original().y_position
            if target_y &lt; -117:
                target_y = -117
            if target_y &gt; 117:
                target_y = 117
            self.set_y(target_y)


class Ball(pytch.Sprite):
    Costumes = ["ball.png"]
    Sounds = ["hit.mp3", "bounce.mp3", "lost.mp3"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(0, 0)

        x_speed = 3
        y_speed = 0
        while True:
            self.change_x(x_speed)

            if self.x_position &gt; 203:
                self.change_x(-x_speed)
                x_speed = -x_speed
                self.start_sound("hit")

            if self.x_position &lt; -203:
                player_y = PlayerBat.the_original().y_position
                position_on_bat = self.y_position - player_y
                if (position_on_bat &gt;= -45) and (position_on_bat &lt;= 45):
                    y_speed = int(position_on_bat / 10)
                    self.change_x(-x_speed)
                    x_speed = -x_speed
                    pytch.broadcast("player-hit")
                    self.start_sound("hit")
                else:
                    for i in range(10):
                        self.change_x(x_speed)
                        self.change_y(y_speed)
                    self.hide()
                    self.start_sound("lost")
                    break

            self.change_y(y_speed)

            if self.y_position &gt; 158 or self.y_position &lt; -158:
                self.change_y(-y_speed)
                y_speed = -y_speed
                self.start_sound("bounce")
' data-slug="trigger-Player-flash-on-hit"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>66</pre></td><td class="linenum"><pre>66</pre></td><td><pre>                    y_speed = int(position_on_bat / 10)</pre></td></tr><tr><td class="linenum"><pre>67</pre></td><td class="linenum"><pre>67</pre></td><td><pre>                    self.change_x(-x_speed)</pre></td></tr><tr><td class="linenum"><pre>68</pre></td><td class="linenum"><pre>68</pre></td><td><pre>                    x_speed = -x_speed</pre></td></tr></tbody><tbody class="diff-add" data-added-text='                    pytch.broadcast("player-hit")
'><tr><td class="linenum"></td><td class="linenum"><pre>69</pre></td><td><pre>                    pytch.broadcast("player-hit")</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>69</pre></td><td class="linenum"><pre>70</pre></td><td><pre>                    self.start_sound("hit")</pre></td></tr><tr><td class="linenum"><pre>70</pre></td><td class="linenum"><pre>71</pre></td><td><pre>                else:</pre></td></tr><tr><td class="linenum"><pre>71</pre></td><td class="linenum"><pre>72</pre></td><td><pre>                    for i in range(10):</pre></td></tr></tbody></table></div></div><p>Now we do something very similar for the robot.  First add a costume:</p><div class="patch-container" data-code-as-of-commit='import pytch


class BoingBackground(pytch.Stage):
    Backdrops = ["table.png"]


class PlayerBat(pytch.Sprite):
    Costumes = ["player-normal.png", "player-flash.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(-215, 0)

        while True:
            if pytch.key_pressed("w") and self.y_position &lt; 117:
                self.change_y(3)
            if pytch.key_pressed("s") and self.y_position &gt; -117:
                self.change_y(-3)

    @pytch.when_I_receive("player-hit")
    def flash_briefly(self):
        self.switch_costume("player-flash")
        pytch.wait_seconds(0.1)
        self.switch_costume("player-normal")


class RobotBat(pytch.Sprite):
    Costumes = ["robot-normal.png", "robot-flash.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(215, 0)

        while True:
            target_y = Ball.the_original().y_position
            if target_y &lt; -117:
                target_y = -117
            if target_y &gt; 117:
                target_y = 117
            self.set_y(target_y)


class Ball(pytch.Sprite):
    Costumes = ["ball.png"]
    Sounds = ["hit.mp3", "bounce.mp3", "lost.mp3"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(0, 0)

        x_speed = 3
        y_speed = 0
        while True:
            self.change_x(x_speed)

            if self.x_position &gt; 203:
                self.change_x(-x_speed)
                x_speed = -x_speed
                self.start_sound("hit")

            if self.x_position &lt; -203:
                player_y = PlayerBat.the_original().y_position
                position_on_bat = self.y_position - player_y
                if (position_on_bat &gt;= -45) and (position_on_bat &lt;= 45):
                    y_speed = int(position_on_bat / 10)
                    self.change_x(-x_speed)
                    x_speed = -x_speed
                    pytch.broadcast("player-hit")
                    self.start_sound("hit")
                else:
                    for i in range(10):
                        self.change_x(x_speed)
                        self.change_y(y_speed)
                    self.hide()
                    self.start_sound("lost")
                    break

            self.change_y(y_speed)

            if self.y_position &gt; 158 or self.y_position &lt; -158:
                self.change_y(-y_speed)
                y_speed = -y_speed
                self.start_sound("bounce")
' data-slug="declare-Robot-hit-flash-costume"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>26</pre></td><td class="linenum"><pre>26</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>27</pre></td><td class="linenum"><pre>27</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>28</pre></td><td class="linenum"><pre>28</pre></td><td><pre>class RobotBat(pytch.Sprite):</pre></td></tr></tbody><tbody class="diff-del"><tr><td class="linenum"><pre>29</pre></td><td class="linenum"></td><td><pre>    Costumes = ["robot-normal.png"]</pre></td></tr></tbody><tbody class="diff-add" data-added-text='    Costumes = ["robot-normal.png", "robot-flash.png"]
'><tr><td class="linenum"></td><td class="linenum"><pre>29</pre></td><td><pre>    Costumes = ["robot-normal.png", "robot-flash.png"]</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>30</pre></td><td class="linenum"><pre>30</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>31</pre></td><td class="linenum"><pre>31</pre></td><td><pre>    @pytch.when_green_flag_clicked</pre></td></tr><tr><td class="linenum"><pre>32</pre></td><td class="linenum"><pre>32</pre></td><td><pre>    def play(self):</pre></td></tr></tbody></table></div></div><p>Define what needs to happen to make the robot bat flash:</p><div class="patch-container" data-code-as-of-commit='import pytch


class BoingBackground(pytch.Stage):
    Backdrops = ["table.png"]


class PlayerBat(pytch.Sprite):
    Costumes = ["player-normal.png", "player-flash.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(-215, 0)

        while True:
            if pytch.key_pressed("w") and self.y_position &lt; 117:
                self.change_y(3)
            if pytch.key_pressed("s") and self.y_position &gt; -117:
                self.change_y(-3)

    @pytch.when_I_receive("player-hit")
    def flash_briefly(self):
        self.switch_costume("player-flash")
        pytch.wait_seconds(0.1)
        self.switch_costume("player-normal")


class RobotBat(pytch.Sprite):
    Costumes = ["robot-normal.png", "robot-flash.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(215, 0)

        while True:
            target_y = Ball.the_original().y_position
            if target_y &lt; -117:
                target_y = -117
            if target_y &gt; 117:
                target_y = 117
            self.set_y(target_y)

    @pytch.when_I_receive("robot-hit")
    def flash_briefly(self):
        self.switch_costume("robot-flash")
        pytch.wait_seconds(0.1)
        self.switch_costume("robot-normal")


class Ball(pytch.Sprite):
    Costumes = ["ball.png"]
    Sounds = ["hit.mp3", "bounce.mp3", "lost.mp3"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(0, 0)

        x_speed = 3
        y_speed = 0
        while True:
            self.change_x(x_speed)

            if self.x_position &gt; 203:
                self.change_x(-x_speed)
                x_speed = -x_speed
                self.start_sound("hit")

            if self.x_position &lt; -203:
                player_y = PlayerBat.the_original().y_position
                position_on_bat = self.y_position - player_y
                if (position_on_bat &gt;= -45) and (position_on_bat &lt;= 45):
                    y_speed = int(position_on_bat / 10)
                    self.change_x(-x_speed)
                    x_speed = -x_speed
                    pytch.broadcast("player-hit")
                    self.start_sound("hit")
                else:
                    for i in range(10):
                        self.change_x(x_speed)
                        self.change_y(y_speed)
                    self.hide()
                    self.start_sound("lost")
                    break

            self.change_y(y_speed)

            if self.y_position &gt; 158 or self.y_position &lt; -158:
                self.change_y(-y_speed)
                y_speed = -y_speed
                self.start_sound("bounce")
' data-slug="define-Robot-hit-handler"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>40</pre></td><td class="linenum"><pre>40</pre></td><td><pre>                target_y = 117</pre></td></tr><tr><td class="linenum"><pre>41</pre></td><td class="linenum"><pre>41</pre></td><td><pre>            self.set_y(target_y)</pre></td></tr><tr><td class="linenum"><pre>42</pre></td><td class="linenum"><pre>42</pre></td><td><pre></pre></td></tr></tbody><tbody class="diff-add" data-added-text='    @pytch.when_I_receive("robot-hit")
    def flash_briefly(self):
        self.switch_costume("robot-flash")
        pytch.wait_seconds(0.1)
        self.switch_costume("robot-normal")

'><tr><td class="linenum"></td><td class="linenum"><pre>43</pre></td><td><pre>    @pytch.when_I_receive("robot-hit")</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>44</pre></td><td><pre>    def flash_briefly(self):</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>45</pre></td><td><pre>        self.switch_costume("robot-flash")</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>46</pre></td><td><pre>        pytch.wait_seconds(0.1)</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>47</pre></td><td><pre>        self.switch_costume("robot-normal")</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>48</pre></td><td><pre></pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>43</pre></td><td class="linenum"><pre>49</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>44</pre></td><td class="linenum"><pre>50</pre></td><td><pre>class Ball(pytch.Sprite):</pre></td></tr><tr><td class="linenum"><pre>45</pre></td><td class="linenum"><pre>51</pre></td><td><pre>    Costumes = ["ball.png"]</pre></td></tr></tbody></table></div></div><p>And then trigger this action when the ball bounces off the robot's
bat:</p><div class="patch-container" data-code-as-of-commit='import pytch


class BoingBackground(pytch.Stage):
    Backdrops = ["table.png"]


class PlayerBat(pytch.Sprite):
    Costumes = ["player-normal.png", "player-flash.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(-215, 0)

        while True:
            if pytch.key_pressed("w") and self.y_position &lt; 117:
                self.change_y(3)
            if pytch.key_pressed("s") and self.y_position &gt; -117:
                self.change_y(-3)

    @pytch.when_I_receive("player-hit")
    def flash_briefly(self):
        self.switch_costume("player-flash")
        pytch.wait_seconds(0.1)
        self.switch_costume("player-normal")


class RobotBat(pytch.Sprite):
    Costumes = ["robot-normal.png", "robot-flash.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(215, 0)

        while True:
            target_y = Ball.the_original().y_position
            if target_y &lt; -117:
                target_y = -117
            if target_y &gt; 117:
                target_y = 117
            self.set_y(target_y)

    @pytch.when_I_receive("robot-hit")
    def flash_briefly(self):
        self.switch_costume("robot-flash")
        pytch.wait_seconds(0.1)
        self.switch_costume("robot-normal")


class Ball(pytch.Sprite):
    Costumes = ["ball.png"]
    Sounds = ["hit.mp3", "bounce.mp3", "lost.mp3"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(0, 0)

        x_speed = 3
        y_speed = 0
        while True:
            self.change_x(x_speed)

            if self.x_position &gt; 203:
                self.change_x(-x_speed)
                x_speed = -x_speed
                pytch.broadcast("robot-hit")
                self.start_sound("hit")

            if self.x_position &lt; -203:
                player_y = PlayerBat.the_original().y_position
                position_on_bat = self.y_position - player_y
                if (position_on_bat &gt;= -45) and (position_on_bat &lt;= 45):
                    y_speed = int(position_on_bat / 10)
                    self.change_x(-x_speed)
                    x_speed = -x_speed
                    pytch.broadcast("player-hit")
                    self.start_sound("hit")
                else:
                    for i in range(10):
                        self.change_x(x_speed)
                        self.change_y(y_speed)
                    self.hide()
                    self.start_sound("lost")
                    break

            self.change_y(y_speed)

            if self.y_position &gt; 158 or self.y_position &lt; -158:
                self.change_y(-y_speed)
                y_speed = -y_speed
                self.start_sound("bounce")
' data-slug="trigger-Robot-flash-on-hit"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>63</pre></td><td class="linenum"><pre>63</pre></td><td><pre>            if self.x_position &gt; 203:</pre></td></tr><tr><td class="linenum"><pre>64</pre></td><td class="linenum"><pre>64</pre></td><td><pre>                self.change_x(-x_speed)</pre></td></tr><tr><td class="linenum"><pre>65</pre></td><td class="linenum"><pre>65</pre></td><td><pre>                x_speed = -x_speed</pre></td></tr></tbody><tbody class="diff-add" data-added-text='                pytch.broadcast("robot-hit")
'><tr><td class="linenum"></td><td class="linenum"><pre>66</pre></td><td><pre>                pytch.broadcast("robot-hit")</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>66</pre></td><td class="linenum"><pre>67</pre></td><td><pre>                self.start_sound("hit")</pre></td></tr><tr><td class="linenum"><pre>67</pre></td><td class="linenum"><pre>68</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>68</pre></td><td class="linenum"><pre>69</pre></td><td><pre>            if self.x_position &lt; -203:</pre></td></tr></tbody></table></div></div></div><div class="chapter-content"><h2>Avoid a stalemate</h2><p>The game can get 'stuck' with the ball bouncing just straight left and
right between the bats.  This is boring.  We'll make it so that if the
ball bounces off the robot bat and is going purely horizontally, we'll
change it to go either gently up or gently down at random.</p><p>To do this, we need to use the random number part of Pytch, by
bringing in the <code>random</code> module:</p><div class="patch-container" data-code-as-of-commit='import pytch
import random


class BoingBackground(pytch.Stage):
    Backdrops = ["table.png"]


class PlayerBat(pytch.Sprite):
    Costumes = ["player-normal.png", "player-flash.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(-215, 0)

        while True:
            if pytch.key_pressed("w") and self.y_position &lt; 117:
                self.change_y(3)
            if pytch.key_pressed("s") and self.y_position &gt; -117:
                self.change_y(-3)

    @pytch.when_I_receive("player-hit")
    def flash_briefly(self):
        self.switch_costume("player-flash")
        pytch.wait_seconds(0.1)
        self.switch_costume("player-normal")


class RobotBat(pytch.Sprite):
    Costumes = ["robot-normal.png", "robot-flash.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(215, 0)

        while True:
            target_y = Ball.the_original().y_position
            if target_y &lt; -117:
                target_y = -117
            if target_y &gt; 117:
                target_y = 117
            self.set_y(target_y)

    @pytch.when_I_receive("robot-hit")
    def flash_briefly(self):
        self.switch_costume("robot-flash")
        pytch.wait_seconds(0.1)
        self.switch_costume("robot-normal")


class Ball(pytch.Sprite):
    Costumes = ["ball.png"]
    Sounds = ["hit.mp3", "bounce.mp3", "lost.mp3"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(0, 0)

        x_speed = 3
        y_speed = 0
        while True:
            self.change_x(x_speed)

            if self.x_position &gt; 203:
                self.change_x(-x_speed)
                x_speed = -x_speed
                pytch.broadcast("robot-hit")
                self.start_sound("hit")

            if self.x_position &lt; -203:
                player_y = PlayerBat.the_original().y_position
                position_on_bat = self.y_position - player_y
                if (position_on_bat &gt;= -45) and (position_on_bat &lt;= 45):
                    y_speed = int(position_on_bat / 10)
                    self.change_x(-x_speed)
                    x_speed = -x_speed
                    pytch.broadcast("player-hit")
                    self.start_sound("hit")
                else:
                    for i in range(10):
                        self.change_x(x_speed)
                        self.change_y(y_speed)
                    self.hide()
                    self.start_sound("lost")
                    break

            self.change_y(y_speed)

            if self.y_position &gt; 158 or self.y_position &lt; -158:
                self.change_y(-y_speed)
                y_speed = -y_speed
                self.start_sound("bounce")
' data-slug="import-random-module"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>1</pre></td><td class="linenum"><pre>1</pre></td><td><pre>import pytch</pre></td></tr></tbody><tbody class="diff-add" data-added-text="import random
"><tr><td class="linenum"></td><td class="linenum"><pre>2</pre></td><td><pre>import random</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>2</pre></td><td class="linenum"><pre>3</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>3</pre></td><td class="linenum"><pre>4</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>4</pre></td><td class="linenum"><pre>5</pre></td><td><pre>class BoingBackground(pytch.Stage):</pre></td></tr></tbody></table></div></div><p>(This is very similar to how you "add an extension" in Scratch to
make more blocks available.)</p><p>Now we have this, we can test if the ball's <code>y_speed</code> is zero, and if
so, use the <code>random.choice()</code> function to make Pytch randomly choose
between the two <code>y_speed</code> values we want:</p><div class="patch-container" data-code-as-of-commit='import pytch
import random


class BoingBackground(pytch.Stage):
    Backdrops = ["table.png"]


class PlayerBat(pytch.Sprite):
    Costumes = ["player-normal.png", "player-flash.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(-215, 0)

        while True:
            if pytch.key_pressed("w") and self.y_position &lt; 117:
                self.change_y(3)
            if pytch.key_pressed("s") and self.y_position &gt; -117:
                self.change_y(-3)

    @pytch.when_I_receive("player-hit")
    def flash_briefly(self):
        self.switch_costume("player-flash")
        pytch.wait_seconds(0.1)
        self.switch_costume("player-normal")


class RobotBat(pytch.Sprite):
    Costumes = ["robot-normal.png", "robot-flash.png"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(215, 0)

        while True:
            target_y = Ball.the_original().y_position
            if target_y &lt; -117:
                target_y = -117
            if target_y &gt; 117:
                target_y = 117
            self.set_y(target_y)

    @pytch.when_I_receive("robot-hit")
    def flash_briefly(self):
        self.switch_costume("robot-flash")
        pytch.wait_seconds(0.1)
        self.switch_costume("robot-normal")


class Ball(pytch.Sprite):
    Costumes = ["ball.png"]
    Sounds = ["hit.mp3", "bounce.mp3", "lost.mp3"]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(0, 0)

        x_speed = 3
        y_speed = 0
        while True:
            self.change_x(x_speed)

            if self.x_position &gt; 203:
                self.change_x(-x_speed)
                x_speed = -x_speed

                if y_speed == 0:
                    y_speed = random.choice([-1, 1])

                pytch.broadcast("robot-hit")
                self.start_sound("hit")

            if self.x_position &lt; -203:
                player_y = PlayerBat.the_original().y_position
                position_on_bat = self.y_position - player_y
                if (position_on_bat &gt;= -45) and (position_on_bat &lt;= 45):
                    y_speed = int(position_on_bat / 10)
                    self.change_x(-x_speed)
                    x_speed = -x_speed
                    pytch.broadcast("player-hit")
                    self.start_sound("hit")
                else:
                    for i in range(10):
                        self.change_x(x_speed)
                        self.change_y(y_speed)
                    self.hide()
                    self.start_sound("lost")
                    break

            self.change_y(y_speed)

            if self.y_position &gt; 158 or self.y_position &lt; -158:
                self.change_y(-y_speed)
                y_speed = -y_speed
                self.start_sound("bounce")
' data-slug="ensure-nonzero-y-speed-on-Robot-hit"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>64</pre></td><td class="linenum"><pre>64</pre></td><td><pre>            if self.x_position &gt; 203:</pre></td></tr><tr><td class="linenum"><pre>65</pre></td><td class="linenum"><pre>65</pre></td><td><pre>                self.change_x(-x_speed)</pre></td></tr><tr><td class="linenum"><pre>66</pre></td><td class="linenum"><pre>66</pre></td><td><pre>                x_speed = -x_speed</pre></td></tr></tbody><tbody class="diff-add" data-added-text="
                if y_speed == 0:
                    y_speed = random.choice([-1, 1])

"><tr><td class="linenum"></td><td class="linenum"><pre>67</pre></td><td><pre></pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>68</pre></td><td><pre>                if y_speed == 0:</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>69</pre></td><td><pre>                    y_speed = random.choice([-1, 1])</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>70</pre></td><td><pre></pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>67</pre></td><td class="linenum"><pre>71</pre></td><td><pre>                pytch.broadcast("robot-hit")</pre></td></tr><tr><td class="linenum"><pre>68</pre></td><td class="linenum"><pre>72</pre></td><td><pre>                self.start_sound("hit")</pre></td></tr><tr><td class="linenum"><pre>69</pre></td><td class="linenum"><pre>73</pre></td><td><pre></pre></td></tr></tbody></table></div></div></div><div class="chapter-content"><h2>Add instructions</h2><p>To tell the player how to use our game, we'll add some instructions at
the top of our code.  We'll do this using a Python <em>comment</em>, which is
a part of your program meant just for human readers — Python ignores
it.  In Python, a line starting with the <code>#</code> character is a comment.
We'll add a short comment explaining how to play Boing:</p><div class="patch-container" data-code-as-of-commit="# You're the player on the left --- use the W/S keys to move your bat!

import pytch
import random


class BoingBackground(pytch.Stage):
    Backdrops = [&quot;table.png&quot;]


class PlayerBat(pytch.Sprite):
    Costumes = [&quot;player-normal.png&quot;, &quot;player-flash.png&quot;]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(-215, 0)

        while True:
            if pytch.key_pressed(&quot;w&quot;) and self.y_position &lt; 117:
                self.change_y(3)
            if pytch.key_pressed(&quot;s&quot;) and self.y_position &gt; -117:
                self.change_y(-3)

    @pytch.when_I_receive(&quot;player-hit&quot;)
    def flash_briefly(self):
        self.switch_costume(&quot;player-flash&quot;)
        pytch.wait_seconds(0.1)
        self.switch_costume(&quot;player-normal&quot;)


class RobotBat(pytch.Sprite):
    Costumes = [&quot;robot-normal.png&quot;, &quot;robot-flash.png&quot;]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(215, 0)

        while True:
            target_y = Ball.the_original().y_position
            if target_y &lt; -117:
                target_y = -117
            if target_y &gt; 117:
                target_y = 117
            self.set_y(target_y)

    @pytch.when_I_receive(&quot;robot-hit&quot;)
    def flash_briefly(self):
        self.switch_costume(&quot;robot-flash&quot;)
        pytch.wait_seconds(0.1)
        self.switch_costume(&quot;robot-normal&quot;)


class Ball(pytch.Sprite):
    Costumes = [&quot;ball.png&quot;]
    Sounds = [&quot;hit.mp3&quot;, &quot;bounce.mp3&quot;, &quot;lost.mp3&quot;]

    @pytch.when_green_flag_clicked
    def play(self):
        self.go_to_xy(0, 0)

        x_speed = 3
        y_speed = 0
        while True:
            self.change_x(x_speed)

            if self.x_position &gt; 203:
                self.change_x(-x_speed)
                x_speed = -x_speed

                if y_speed == 0:
                    y_speed = random.choice([-1, 1])

                pytch.broadcast(&quot;robot-hit&quot;)
                self.start_sound(&quot;hit&quot;)

            if self.x_position &lt; -203:
                player_y = PlayerBat.the_original().y_position
                position_on_bat = self.y_position - player_y
                if (position_on_bat &gt;= -45) and (position_on_bat &lt;= 45):
                    y_speed = int(position_on_bat / 10)
                    self.change_x(-x_speed)
                    x_speed = -x_speed
                    pytch.broadcast(&quot;player-hit&quot;)
                    self.start_sound(&quot;hit&quot;)
                else:
                    for i in range(10):
                        self.change_x(x_speed)
                        self.change_y(y_speed)
                    self.hide()
                    self.start_sound(&quot;lost&quot;)
                    break

            self.change_y(y_speed)

            if self.y_position &gt; 158 or self.y_position &lt; -158:
                self.change_y(-y_speed)
                y_speed = -y_speed
                self.start_sound(&quot;bounce&quot;)
" data-slug="add-player-instructions"><div class="patch"><table><tbody class="diff-add" data-added-text="# You're the player on the left --- use the W/S keys to move your bat!

"><tr><td class="linenum"></td><td class="linenum"><pre>1</pre></td><td><pre># You're the player on the left --- use the W/S keys to move your bat!</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>2</pre></td><td><pre></pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>1</pre></td><td class="linenum"><pre>3</pre></td><td><pre>import pytch</pre></td></tr><tr><td class="linenum"><pre>2</pre></td><td class="linenum"><pre>4</pre></td><td><pre>import random</pre></td></tr><tr><td class="linenum"><pre>3</pre></td><td class="linenum"><pre>5</pre></td><td><pre></pre></td></tr></tbody></table></div></div></div><div class="chapter-content"><h2>Challenges</h2><p>Here are some ways you could make the game better.  Both of these
tasks are quite advanced, so your first step should be to think about
how to break the job down into manageable pieces.</p><ul>
<li>
<p>At the moment, the human player has no chance against the computer.
  Can you make it so the computer does <em>not</em> always win?</p>
</li>
<li>
<p>At the moment, the game stops once the player misses the ball.  Can
  you instead keep score, and make it so the winner is the first to
  get ten points?  This only makes sense if you've already made it so
  the computer sometimes misses!</p>
</li>
</ul><p>You could also experiment with changing the physics of the game, for
example:</p><ul>
<li>Add gravity, so the ball falls towards the bottom of the screen.
  Think about how the <code>y_speed</code> of the <code>Ball</code> sprite needs to change
  to give the right effect.</li>
</ul><p>Can you think of other changes or improvements?</p></div><div class="chapter-content"><h2>Credits</h2><p>Many thanks to the Raspberry Pi Press for making the contents of their
<em>Code The Classics</em> book available under a Creative Commons licence.  We
have used their code for inspiration, and also the images and sounds.</p><h3>Detailed credits</h3><div class="asset-credits"><p class="credit-intro">For <code class="asset-filename">table.png</code> (used in the project):</p><div class="credits"><p>The image <a href="https://github.com/Wireframe-Magazine/Code-the-Classics/blob/master/boing-master/images/table.png"><em>Boing table</em></a>
is copyright Raspberry Pi Trading Ltd, 2019.  We use it under the
<a href="https://creativecommons.org/licenses/by-nc-sa/3.0/">Creative Commons Attribution-NonCommercial-ShareAlike
3.0</a> licence.  We
have changed its size to fit the size of the Pytch stage.</p></div><p class="credit-intro">For <code class="asset-filename">player-normal.png</code> (used in the project):</p><div class="credits"><p>The image <a href="https://github.com/Wireframe-Magazine/Code-the-Classics/blob/master/boing-master/images/bat00.png"><em>first player normal
bat for Boing</em></a>
is copyright Raspberry Pi Trading Ltd, 2019.  We use it under the
<a href="https://creativecommons.org/licenses/by-nc-sa/3.0/">Creative Commons Attribution-NonCommercial-ShareAlike
3.0</a> licence.  We
have reduced its size.</p></div><p class="credit-intro">For <code class="asset-filename">ball.png</code> (used in the project):</p><div class="credits"><p>The image <a href="https://github.com/Wireframe-Magazine/Code-the-Classics/blob/master/boing-master/images/ball.png"><em>ball for Boing</em></a>
is copyright Raspberry Pi Trading Ltd, 2019.  We use it under the
<a href="https://creativecommons.org/licenses/by-nc-sa/3.0/">Creative Commons Attribution-NonCommercial-ShareAlike
3.0</a> licence.</p></div><p class="credit-intro">For <code class="asset-filename">robot-normal.png</code> (used in the project):</p><div class="credits"><p>The image <a href="https://github.com/Wireframe-Magazine/Code-the-Classics/blob/master/boing-master/images/bat10.png"><em>second player normal
bat for Boing</em></a>
is copyright Raspberry Pi Trading Ltd, 2019.  We use it under the
<a href="https://creativecommons.org/licenses/by-nc-sa/3.0/">Creative Commons Attribution-NonCommercial-ShareAlike
3.0</a> licence.  We
have reduced its size.</p></div><p class="credit-intro">For <code class="asset-filename">bounce.mp3</code>, <code class="asset-filename">hit.mp3</code>, <code class="asset-filename">lost.mp3</code> (used in the project):</p><div class="credits"><p>The sound files</p><ul>
<li><a href="https://github.com/Wireframe-Magazine/Code-the-Classics/blob/master/boing-master/sounds/bounce_synth0.ogg"><em>Synth bounce sound for Boing</em></a></li>
<li><a href="https://github.com/Wireframe-Magazine/Code-the-Classics/blob/master/boing-master/sounds/hit_synth0.ogg"><em>Synth hit sound for Boing</em></a></li>
<li><a href="https://github.com/Wireframe-Magazine/Code-the-Classics/blob/master/boing-master/sounds/score_goal0.ogg"><em>Score goal sound for Boing</em></a></li>
</ul><p>are copyright Raspberry Pi Trading Ltd, 2019.  We use them under the
<a href="https://creativecommons.org/licenses/by-nc-sa/3.0/">Creative Commons Attribution-NonCommercial-ShareAlike
3.0</a> licence.  We
have converted the original OGG files to MP3 format.</p></div><p class="credit-intro">For <code class="asset-filename">player-flash.png</code>, <code class="asset-filename">robot-flash.png</code> (used in the project):</p><div class="credits"><p>The images <a href="https://github.com/Wireframe-Magazine/Code-the-Classics/blob/master/boing-master/images/bat01.png"><em>first player flashing
bat for
Boing</em></a>
and <a href="https://github.com/Wireframe-Magazine/Code-the-Classics/blob/master/boing-master/images/bat11.png"><em>second player flashing
bat for Boing</em></a>
are copyright Raspberry Pi Trading Ltd, 2019.  We use them under the
<a href="https://creativecommons.org/licenses/by-nc-sa/3.0/">Creative Commons Attribution-NonCommercial-ShareAlike
3.0</a> licence.  We
have reduced their size.</p></div><p class="credit-intro">For <code class="asset-filename">summary-screenshot.png</code> (used in the tutorial text/summary):</p><div class="credits"><p>This screenshot was created by the Pytch team to illustrate the Boing
project.  It contains elements from <a href="https://github.com/Wireframe-Magazine/Code-the-Classics/blob/master/boing-master/"><em>the Code the Classics Boing
game</em></a>,
and to that extent is copyright Raspberry Pi Trading Ltd, 2019.  We
use the image elements under the
<a href="https://creativecommons.org/licenses/by-nc-sa/3.0/">Creative Commons Attribution-NonCommercial-ShareAlike
3.0</a> licence.  We
have composited the original images, and resized the result.</p></div></div></div></div>